4

どこかに数千行のコードがあり、更新しすぎると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を最初から作成することを考えていましたが、皆さんがもっと簡単な解決策を持っているかどうかを確認したいと思います。

4

2 に答える 2

8

エラーの一部は、イベント スレッドの外部から Swing コンポーネントにアクセスしていることです! はい、setText()はスレッドセーフですが、Swing メソッドは、明示的に宣言されていない限り、スレッドセーフではありません。したがって、setCaretPosition()はスレッドセーフではなく、イベント スレッドからアクセスする必要があります。これが、アプリケーションが最終的にフリーズする理由であることはほぼ間違いありません。

注: はそのメソッドを からJTextPane継承し、そのメソッドはから継承します。これは、前の段落のリンクがJavaDoc ページに移動しないことを説明しています。setText()JEditorPanesetCaretPositionJTextComponentJTextPane

setCaretPosition()スレッドセーフにするには、少なくともイベント スレッド内から呼び出す必要があります。これは、次のようなコードで実行できます。

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

またsetCaretPosition()、イベント スレッド内から呼び出す必要があるためsetText()、同じ場所から呼び出すこともできます。

キャレットの位置を手動で設定する必要がない場合もあります。JTextComponentの JavaDoc の「Caret Changes」セクションを確認してください。

最後に、一連の 2 つの記事をチェックすることをお勧めします。

于 2009-03-22T02:54:41.493 に答える
1

insertString()これが機能するかどうかはわかりませんが、テキスト ペインのDocumentインスタンスのメソッドを使用してみることができます。ドキュメントの最後に単一のスペースを置き、そのスペースの後にキャレットを配置したままにします。ただし、文字列を挿入するときは、スペースの前に挿入してください。そうすれば、キャレットの位置はドキュメントの最後に自動的に残ります。

テキスト ペインが 2 回再描画されている可能性があると考えていsetText()ますsetCaretPosition()。ただし、確かではありません (Swing を使用してからしばらく経ちます)。

于 2009-03-21T21:12:33.453 に答える