簡體   English   中英

Swing 組件在大量更新時閃爍

[英]Swing component flickering when updated a lot

我在某處有幾千行代碼,我注意到當我更新太多 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 版本,但我想看看你們是否有更簡單的解決方案。

您的部分錯誤是您正在從事件線程外部訪問 Swing 組件,是的, setText()是線程安全的,但 Swing 方法不是線程安全的,除非它們明確聲明為這樣。 因此, setCaretPosition()不是線程安全的,必須從事件線程訪問。 這幾乎肯定是您的應用程序最終凍結的原因。

注意: JTextPaneJEditorPane繼承其setText()方法,從JTextComponent繼承其setCaretPosition方法,這解釋了上一段中的鏈接不會轉到JTextPane JavaDoc 頁面。

為了線程安全,您至少需要從事件線程中調用setCaretPosition() ,您可以使用如下代碼執行此操作:

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

而且由於您必須從事件線程中調用setCaretPosition() ,因此您也可以從同一位置調用setText()

您可能不需要手動設置插入符號 position。 查看JTextComponent的 JavaDoc 中的“插入符號更改”部分。

最后,您可能想查看一系列兩篇文章:

不確定這是否可行,但您可以嘗試使用文本窗格的Document實例的insertString()方法。 我會嘗試在文檔末尾有一個空格,並將插入符號放在該空格之后; 但是當你插入一個字符串時,將它插入到空格之前。 這樣插入符號 position 將自動保留在文檔的末尾。

我認為文本窗格可能會被重繪兩次,一次是在您調用setText()時,一次是在您調用setCaretPosition()時,這可能會導致閃爍。 不過不確定(自從我使用 Swing 以來已經有一段時間了)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM