Java
 Computer >> コンピューター >  >> プログラミング >> Java

JavaでJTextAreaに行番号を表示する方法【DocumentListener活用】

JTextAreaJTextComponentクラスのサブクラスであり、複数行のテキストを表示したり、ユーザーにテキストを入力させたりできるSwingのテキストコンポーネントです。また、CaretListenerインターフェースを実装することで、キャレット(カーソル)の移動イベントを監視することも可能です。

しかし、JTextAreaはデフォルトでは行番号を表示しません。行番号を表示したい場合は、DocumentListenerインターフェースを使ってドキュメントの変更(文字の挿入・削除など)を検知し、その都度行番号を再描画する仕組みを自前で実装する必要があります。

実装のポイント

  • 行番号表示用に別のJTextAreaを用意し、編集不可(setEditable(false))に設定する
  • 本文側のJTextAreaにDocumentListenerを登録し、テキストが変更されるたびに行番号を更新する
  • Documentのルート要素から現在の行数を取得し、行番号の文字列を組み立てる
  • JScrollPaneのsetRowHeaderView()メソッドを使い、行番号エリアを行ヘッダーとして配置する

サンプルコード

import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.Element;

public class LineNumberTextAreaTest extends JFrame {
    private static JTextArea textArea;
    private static JTextArea lines;
    private JScrollPane jsp;

    public LineNumberTextAreaTest() {
        setTitle("LineNumberTextArea Test");
        jsp = new JScrollPane();
        textArea = new JTextArea();
        lines = new JTextArea("1");
        lines.setBackground(Color.LIGHT_GRAY);
        lines.setEditable(false);
        // JTextArea内に行番号を実装するコード
        textArea.getDocument().addDocumentListener(new DocumentListener() {
            public String getText() {
                int caretPosition = textArea.getDocument().getLength();
                Element root = textArea.getDocument().getDefaultRootElement();
                String text = "1" + System.getProperty("line.separator");
                for(int i = 2; i < root.getElementIndex(caretPosition) + 2; i++) {
                    text += i + System.getProperty("line.separator");
                }
                return text;
            }
            @Override
            public void changedUpdate(DocumentEvent de) {
                lines.setText(getText());
            }
            @Override
            public void insertUpdate(DocumentEvent de) {
                lines.setText(getText());
            }
            @Override
            public void removeUpdate(DocumentEvent de) {
                lines.setText(getText());
            }
        });
        jsp.getViewport().add(textArea);
        jsp.setRowHeaderView(lines);
        add(jsp);
        setSize(400, 275);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        setVisible(true);
    }
    public static void main(String[] args) {
        new LineNumberTextAreaTest();
    }
}

コードの解説

getText()メソッドでは、ドキュメントの長さからキャレット位置を求め、getDefaultRootElement()で取得したルート要素に対してgetElementIndex()を呼び出すことで、現在の行数を計算しています。その行数分だけ「1」から順に行番号と改行コード(System.getProperty("line.separator"))を連結した文字列を生成します。

insertUpdate()、removeUpdate()、changedUpdate()の各メソッドは、テキストの挿入・削除・属性変更の際に呼び出され、それぞれ行番号表示用のJTextArea(lines)に行番号文字列をセットし直します。これにより、エディタの内容と行番号が常に同期されます。

実行結果

JavaでJTextAreaに行番号を表示する方法【DocumentListener活用】

プログラムを実行すると、テキストエリアの左側にグレー背景の行番号エリアが表示されます。テキストを入力して改行するたびに行番号が自動的に追加され、行を削除すれば行番号も連動して減っていきます。

  1. JavaのJTextAreaで行の折り返しと単語単位の折り返しを実装する方法

    JTextAreaは、テキストを表示したり、ユーザーにテキストを入力させたりするための複数行対応のテキストコンポーネントです。JTextAreaコンポーネントの機能を実装する際には、CaretListenerインターフェースが活用されます。また、JTextAreaクラスは、JavaのJTextComponentクラスを継承しています。 以下の例では、JTextAreaクラスを実装し、ItemListenerインターフェースを使って、ユーザーが「word wrap(単語単位の折り返し)」と「line wrap(行の折り返し)」のチェックボックスを切り替えられるようにしています。 コード例 im

  2. JavaでJTextFieldに入力できる文字数を制限する方法(PlainDocument活用)

    JTextFieldは、Swingアプリケーションにおいてユーザーにテキストを1行形式で入力させるための、最も重要なコンポーネントの一つです。フォームや検索ボックスなど、さまざまな場面で利用されますが、場合によっては「入力できる文字数に上限を設けたい」という要件が発生します。このような文字数制限は、PlainDocumentクラスを継承したカスタムドキュメントを作成することで簡単に実現できます。ドキュメントはJTextFieldの内部でテキストデータを管理する役割を持つため、ここで挿入処理を制御すれば、上限を超える文字入力を防ぐことが可能です。実装のポイントPlainDocumentを継承した