質問

どこかに数千行のコードがあり、更新しすぎると 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() はスレッドセーフではないため、イベント スレッドからアクセスする必要があります。アプリケーションが最終的にフリーズするのは、ほぼ確実にこれが原因です。

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

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

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

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

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

最後に、次の 2 つの記事シリーズをご覧ください。

他のヒント

これが機能するかどうかわからないが、あなたは、テキスト・ペインのinsertString()インスタンスのDocumentメソッドを使用して試みることができます。私は、文書の最後に単一のスペースを有し、かつ、そのスペースの後に配置キャレットを維持しようとするだろう。あなたは、文字列を挿入するときには、スペースの前に挿入します。こうすることで、キャレット位置が自動的に文書の最後に残るます。

私はあなたがsetText()を呼び出すときに一度setCaretPosition()を呼び出し、一度際、テキスト・ペインが二回再描画を取得するかもしれないと考えている、それがちらつきに貢献している可能性があります。わからない、しかし(私はスイングで働いていたので、それがしばらくしている)。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top