Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Swing组件在大量更新时闪烁_Java_Multithreading_Swing_Flicker_Jtextpane - Fatal编程技术网

Java Swing组件在大量更新时闪烁

Java Swing组件在大量更新时闪烁,java,multithreading,swing,flicker,jtextpane,Java,Multithreading,Swing,Flicker,Jtextpane,我在某个地方有几千行代码,我注意到我的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) {

我在某个地方有几千行代码,我注意到我的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
作为最终变量,这样它就不会被构造数百次。不过,这种闪烁是显而易见的,也是不可接受的。几分钟后,部件完全冻结。我必须非常快地更新组件,更新时必须将窗格滚动到底部


我一直在考虑从头开始制作我自己的JTextPane版本,但我想看看你们是否有更简单的解决方案。

不确定这是否可行,但您可以尝试使用文本窗格的
文档
实例的
insertString()
方法。我会尝试在文档末尾留一个空格,并将插入符号放在该空格之后;但插入字符串时,请将其插入空格之前。这样,插入符号位置将自动保留在文档末尾


我认为文本窗格可能会被重绘两次,一次是在调用
setText()
时,一次是在调用
setCaretPosition()
时,这可能是导致闪烁的原因。但不确定(我已经有一段时间没有使用Swing了)。

部分错误在于您正在从事件线程外部访问Swing组件!是的,它是线程安全的,但是Swing方法不是线程安全的,除非它们被显式声明为线程安全。因此,它不是线程安全的,必须从事件线程访问。这几乎肯定就是应用程序最终冻结的原因

注意:
JTextPane
继承了
JEditorPane
中的
setText()
方法和
JTextComponent
中的
setCaretPosition
方法,这解释了上一段中没有指向JavaDoc页面的链接

为了线程安全,您确实需要至少从事件线程中调用
setCaretPosition()
,您可以使用如下代码:

SwingUtilities.invokeAndWait(new Runnable() {
  public void run() {
    a.setText(b.toString());
    a.setCaretPosition(b.length());
  }
}
由于必须从事件线程内调用
setCaretPosition()
,因此也可以从同一位置调用
setext()

您可能不需要手动设置插入符号位置。请查看JavaDoc中的“插入符号更改”部分,了解更多信息

最后,您可能想查看由两篇文章组成的系列文章:


为什么奇怪地强调“专家”一词?你认为侮辱我们会得到更好的答案吗?对不起,无意冒犯。编辑。我真的不能把所有这些都放在EDT中,因为sleep()会把它阻塞得太厉害,以至于组件会完全冻结。不是sleep!但是setCaretPosition必须在EDT中。否则你会经历偶尔的(或不是那么偶然的)挂起。回答得好;只需要
添加到代码末尾。