我在某个地方有几千行代码,我注意到当我更新太多时我的 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();
}
});
}
}
这是一个终端 (cmd) 风格的 GUI 组件--
我想我已经在这里做了我能做的所有优化,包括将 \n
作为最终变量,这样它就不会被构造数百次。尽管如此,闪烁仍然很明显且 Not Acceptable 。几分钟后,组件完全卡住。我必须非常快速地更新组件,并且更新时 Pane 必须滚动到底部。
我一直在考虑从头开始制作我自己的 JTextPane 版本,但我想看看你们是否有更简单的解决方案。
最佳答案
您的部分错误是您正在从事件线程外部访问 Swing 组件!是的,setText()是线程安全的,但 Swing 方法不是线程安全的,除非它们被显式声明为线程安全的。因此,setCaretPosition()不是线程安全的,必须从事件线程访问。这几乎可以肯定是您的应用程序最终卡住的原因。
注意:JTextPane
从 JEditorPane
继承了它的 setText()
方法,从 继承了它的
,它解释了上一段中的链接不会转到 setCaretPosition
方法JTextComponentJTextPane
JavaDoc 页面。
要线程安全,您确实至少需要从事件线程中调用 setCaretPosition()
,您可以使用如下代码来实现:
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
a.setText(b.toString());
a.setCaretPosition(b.length());
}
}
并且由于您必须从事件线程中调用 setCaretPosition()
,因此您也可以从同一位置调用 setText()
。
您可能不需要手动设置插入符位置。查看 JTextComponent 的 JavaDoc 中的“插入符更改”部分.
最后,您可能想查看两篇系列文章:
关于java - 大量更新时 Swing 组件闪烁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/669979/