大量更新时,Swing组件会闪烁 [英] Swing component flickering when updated a lot

查看:296
本文介绍了大量更新时,Swing组件会闪烁的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在某处有几千行代码,当我更新太多时,我注意到我的JTextPane闪烁了.我在这里写了一个简化的版本:

I've got a couple thousand lines of code somewhere and I've noticed that my JTextPane flickers when I update it too much.. I wrote a simplified version here:

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组件-

This is for a terminal (cmd) style GUI component--

我想我已经在这里做了所有可能的优化,包括将\n作为最终变量,这样它就不会被构造成数百次了.尽管如此,闪烁仍然是明显的和不可接受的.几分钟后,组件完全冻结.我必须非常快速地更新组件,并且更新后必须将窗格滚动到底部.

I think I've made all the optimizations I could here, including having \n as a final variable so it won't be constructed hundreds of times. Still, the flickering is noticeable and unacceptable. After a few minutes, the component freezes completely. I must update the component very quickly, and the pane must be scrolled to the bottom when updated.

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

I've been thinking about making my own version of JTextPane from scratch, but I'd like to see if you guys have an easier solution.

推荐答案

部分错误是您正在从事件线程外部访问Swing组件!是的, setText( 是线程安全的,但是Swing方法不是线程安全的,除非明确声明它们是这样的.因此, setCaretPosition()不是线程安全的,必须从事件线程进行访问.这几乎可以肯定是您的应用程序最终冻结的原因.

Part of your error is that you are accessing a Swing component from outside the event thread! Yes, setText() is thread-safe, but Swing methods are not Thread-safe unless they are explicitly declared as such. Thus, setCaretPosition() is not Thread-safe and must be accessed from the event thread. This is almost certainly why your application eventually freezes.

注意:JTextPaneJEditorPane继承其setText()方法,从JTextComponent继承其setCaretPosition方法,这解释了上一段中的链接不会转到

NOTE: JTextPane inherits its setText() method from JEditorPane and its setCaretPosition method from JTextComponent, which explains the links in the previous paragraph not going to the JTextPane JavaDoc page.

要确保线程安全,您实际上至少需要从事件线程中调用setCaretPosition(),您可以使用以下代码执行此操作:

To be Thread-safe, you really need to at least call setCaretPosition() from within the event thread, which you can do with code like this:

SwingUtilities.invokeAndWait(new Runnable() {
  public void run() {
    a.setText(b.toString());
    a.setCaretPosition(b.length());
  }
}

而且由于您必须从事件线程内调用setCaretPosition(),因此您也可能从同一位置调用setText().

And since you have to call setCaretPosition() from within the event thread, you might as well also call setText() from the same place.

可能不需要手动设置插入标记的位置.在JavaDoc中查看 JTextComponent .

It's possible that you may not need to manually set the caret position. Check out the section "Caret Changes" in the JavaDoc for JTextComponent.

最后,您可能需要查看一系列两篇文章:

Finally, you may want to check out a series of two articles:

  • Faster JTextPane Text Insertion (Part I)
  • Faster JTextPane Text Insertion (Part II)

这篇关于大量更新时,Swing组件会闪烁的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆