Bai*_* Li 3 java swing multithreading jtextpane flicker
我在某处有几千行代码,我注意到当我更新它时,我的JTextPane闪烁......我在这里写了一个简化版本:
import java.awt.*;
import javax.swing.*;
public class Test
{
static JFrame f;
static JTextPane a;
static final String NL = "\n";
public static void main(String... args)
{
EventQueue.invokeLater(new Runnable(){
public void run()
{
f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
f.setSize(400, 300);
f.setLocationRelativeTo(null);
a = new JTextPane();
f.add(new JScrollPane(a));
new Thread(new Runnable(){
public void run()
{
int i = 0;
StringBuffer b = new StringBuffer();
while(true)
{
b.append(++i+NL);
a.setText(b.toString());
a.setCaretPosition(b.length());
try{Thread.sleep(10);}catch(Exception e){}
}
}
}).start();
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
这是针对终端(cmd)样式的GUI组件 -
我想我已经完成了所有优化,包括\n作为最终变量,因此不会构建数百次.然而,闪烁是显而易见的,也是不可接受的.几分钟后,组件完全冻结.我必须非常快速地更新组件,并且在更新时必须将窗格滚动到底部.
我一直在考虑从头开始创建自己的JTextPane版本,但我想看看你们是否有更简单的解决方案.
您的错误的一部分是您从事件线程外部访问Swing组件!是的,setText()是线程安全的,但Swing方法不是线程安全的,除非它们是显式声明的.因此,setCaretPosition()不是线程安全的,必须从事件线程访问.这几乎可以肯定您的应用程序最终冻结的原因.
注意: JTextPane从其继承其setText()方法JEditorPane及其setCaretPosition方法JTextComponent,这解释了前一段中的链接没有进入JTextPaneJavaDoc页面.
要成为线程安全的,你真的需要至少setCaretPosition()从事件线程中调用,你可以使用这样的代码:
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
a.setText(b.toString());
a.setCaretPosition(b.length());
}
}
Run Code Online (Sandbox Code Playgroud)
因为你必须setCaretPosition()从事件线程中调用,所以你也可以setText()从同一个地方调用.
您可能不需要手动设置插入位置.查看JavaDoc for JTextComponent中的"Caret Changes"部分.
最后,您可能想查看一系列两篇文章:
| 归档时间: |
|
| 查看次数: |
3693 次 |
| 最近记录: |