7

メッセージを表示するためのJTextAreaを備えたサービスのGUIを作成しようとしています。各メッセージは単一行に書き込まれ、必要に応じてワードラップされます。

メッセージはソケットを介して到着するため、JTextAreaを更新するために使用しているのは単なる.append(message)です。これらの行を50または100に制限する必要があり、各行の文字数を制限する必要はありません。

JTextAreaの行数を制限する方法がある場合、またはそれを行う別の方法がある場合はどうなりますか?

私はこの件で本当に援助を使うことができました。

編集

問題は、各クライアントが無限の行を送信できることです。これらの行はすべて読み取り可能である必要があるため、これはJTextAreaの行数の単純なチェックではありません。新しい行を表示するには、古い行を削除する必要があります。

4

4 に答える 4

7

以下は、機能しているように見える大まかなDocumentFilterです。その基本的なアプローチは、挿入/追加を実行させ、事後の行数を照会し、最大値を超える場合は、必要に応じて最初から行を削除することです。

注意:textAreaメソッドでカウントされる行は、レイアウトされた実際の行ではなく、(おそらく@Staniからの確認を待っている)行-between-crです。正確な要件に応じて、それらはあなたに適している場合とそうでない場合があります(そうでない場合は、Stanのユーティリティメソッドを使用してください)

私は驚いたが、それが安全かどうか完全にはわからなかった

  • 驚いたことに、insertメソッドは呼び出されず、代わりにreplaceメソッドを実装する必要があります(本番環境のコードではおそらく両方)
  • textAreaがフィルターメソッドで最新の値を返すことが保証されているかどうかわからない(おそらくそうではない場合、長さチェックはinvokeLaterでラップできます)

いくつかのコード:

public class MyDocumentFilter extends DocumentFilter {

    private JTextArea area;
    private int max;

    public MyDocumentFilter(JTextArea area, int max) {
        this.area = area;
        this.max = max;
    }

    @Override
    public void replace(FilterBypass fb, int offset, int length,
            String text, AttributeSet attrs) throws BadLocationException {
        super.replace(fb, offset, length, text, attrs);
        int lines = area.getLineCount();
        if (lines > max) {
            int linesToRemove = lines - max -1;
            int lengthToRemove = area.getLineStartOffset(linesToRemove);
            remove(fb, 0, lengthToRemove);
        }
    }
}

// usage
JTextArea area = new JTextArea(10, 10);
((AbstractDocument) area.getDocument()).setDocumentFilter(new MyDocumentFilter(area, 3));
于 2012-08-28T14:45:30.810 に答える
7

これを使用して行と列を取得します

行数をチェックし(doc.getLength()オフセットを渡す)、テキストが追加されないようにするDocumentFilterを追加します。

または、ダミーの非表示のJTextAreaを作成して、そこにすべてのテキストを追加することもできます。次に、最後に許可された行を測定し、テキストを切り取ります。

于 2012-08-28T13:54:13.120 に答える
6

これはより効率的でしょうか?

final int SCROLL_BUFFER_SIZE = 100;
public void trunkTextArea(JTextArea txtWin)
{
    int numLinesToTrunk = txtWin.getLineCount() - SCROLL_BUFFER_SIZE;
    if(numLinesToTrunk > 0)
    {
        try
        {
            int posOfLastLineToTrunk = txtWin.getLineEndOffset(numLinesToTrunk - 1);
            txtWin.replaceRange("",0,posOfLastLineToTrunk);
        }
        catch (BadLocationException ex) {
            ex.printStackTrace();
        }
    }
}
于 2015-05-08T22:24:58.203 に答える
1

私のアプローチは、JTextPaneのコンテンツをドキュメントとして使用します。プログラムがドキュメントの最後にテキストを何度も追加していることを前提としているため、doc.getCharacterElement(1)を呼び出すと、基本的にコードの最初の行を表すリーフ要素が取得されます。これを削除したいので、その要素の開始オフセットと終了オフセットを取得し、removeメソッドを呼び出して最も早いテキストを切り取ります。

これは、合計文字数が100万文字を超えているかどうかを確認するか(以下で行ったように)、またはすでに追加した行数に基づいて選択的に実行できます。

すでに追加されている行数に基づいて計算する場合は、JTextPaneに印刷するたびにインクリメントされるフィールドが必要になります。これにより、このコードは、新しいテキスト行を印刷するたびに1回実行され、カウントが最大値。

        JTextPane pane = ...
        StyledDocument doc = pane.getStyledDocument();
        int size = doc.getLength();
        if (size > 1000000) {
            out.println("Size: " + size);
            out.println(":" + 1);
            int i = 0;
            Element e = doc.getCharacterElement(i + 1);
            int start = e.getStartOffset();
            int end = e.getEndOffset();

            try {
                doc.remove(start, end);
            } catch (BadLocationException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
        }

乾杯!

于 2015-06-01T23:10:50.787 に答える