WisdomSoft - for your serial experiences.

8.1 1行テキスト

ユーザーが任意のテキストを入力できすテキストフィールドを作成します。入力位置を表すキャレットや、テキストの選択範囲なども細かく制御・カスタマイズできます。

8.1.1 文字の入力

Component クラスに KeyListener オブジェクトを追加すればコンポーネントに対するキーボードからの入力を受けることができますが、より汎用的に、ユーザーに文字を入力させる場合はテキスト入力を専門とするコンポーネントを使ったほうが良いでしょう。Swing コンポーネントは極めて柔軟に、再利用性の高い設計の下でテキストコンポーネントが提供されています。

Swing のテキスト入力コンポーネントは、必ず javax.swing.text.JTextComponent クラスをスーパークラスとしています。

javax.swing.text.JTextComponent クラス
java.lang.Object
  |
  +--java.awt.Component
        |
        +--java.awt.Container
              |
              +--javax.swing.JComponent
                    |
                    +--javax.swing.text.JTextComponent
public abstract class JTextComponent
	extends JComponent implements Scrollable, Accessible

JTextComponent クラスのすべてのテキスト入力コンポーネントに共通する基本的なメソッドを提供しています。テキスト入力位置を表すキャレット、選択範囲、編集などは、このクラスのメソッドを使って共通した操作で行うことができます。

表1 JTextComponent クラスのメソッド(抜粋)
メソッド 解説
public void setText(String t)

テキストコンポーネントのテキストに、指定されたテキストを設定する。

public String getText() テキストコンポーネントに格納されたテキストを返す。
public void setSelectionStart(int selectionStart) 選択開始を、指定された位置に設定する。
public int getSelectionStart() 選択したテキストの開始位置を返す。
public void setSelectionEnd(int selectionEnd) 選択領域の末尾を、指定された位置に設定する。
public int getSelectionEnd() 選択したテキストの末尾位置を返す。
public void selectAll() テキストコンポーネント内のすべてのテキストを選択する。
public String getSelectedText() テキストコンポーネントに格納された選択されているテキストを返す。
public void setEditable(boolean b) テキストコンポーネントが編集可能かどうかを設定する。
public boolean isEditable() テキストコンポーネントが編集可能かどうかを示すブール型を返す。

表1は、JTextComponent クラスの中でもテキスト入力と選択に関する基本的なメソッドを列挙しています。テキスト入力コンポーネントはどのような形であれ内部に入力された文字列を保有します。入力されたテキストは getText() メソッドで取得し、選択されているテキストは getSelectedText() メソッドで得ることができます。

もっとも単純なテキスト入力コンポーネントは、JTextComponent クラスを継承する javax.swing.JTextField クラスです。

javax.swing.JTextField クラス
java.lang.Object
  |
  +--java.awt.Component
        |
        +--java.awt.Container
              |
              +--javax.swing.JComponent
                    |
                    +--javax.swing.text.JTextComponent
                          |
                          +--javax.swing.JTextField
public class JTextField extends JTextComponent implements SwingConstants

このクラスは、1行のテキストを入力するためのコンポーネントです。何らかの文字列や数字を入力してもらうコンポーネントとして利用することができ、ユーザー名の入力など、アプリケーションがユーザーと対話する手段として利用することができるでしょう。

表2 JTextField のコンストラクタとメソッド(抜粋)
コンストラクタ 解説
public JTextField() 新しい TextField を構築する。
public JTextField(String text) 指定されたテキストで初期化される新しい TextField を構築する。
public JTextField(int columns) 指定された列数で新しい空の TextField を構築する。
public JTextField(String text, int columns) 指定されたテキストと列数で初期化される新しい TextField を構築する。
public JTextField(Document doc, String text, int columns)

指定されたテキストストレージと列数を使って新しい JTextField を構築する。

メソッド
public void addActionListener(ActionListener l) 指定されたアクションリスナーを追加する。
public void removeActionListener(ActionListener l) 指定されたアクションリスナーを削除する。
public ActionListener[] getActionListeners() 設定されているすべての ActionListener の配列を返す。
public void setHorizontalAlignment(int alignment) テキストの水平配置を設定する。
public int getHorizontalAlignment() テキストの水平配置を返す。
public void setColumns(int columns) この TextField の列数を設定し、配置を無効にする。
public int getColumns() この TextField の列数を返す。
protected int getColumnWidth() 列幅を取得する。

JTextField クラスのコンポーネントは、アクションリスナを登録することができます。ユーザーがテキストの入力を Enter キーを押して終了すると登録しているリスナが呼び出されます。

setHorizontalAlignment() メソッドで、テキスト表示するコンポーネント内の水平位置を指定することができます。このメソッドが扱う数値は SwingConstans インタフェースで宣言されているフィールド定数で、JTextField.LEFT、JTextField.CENTER、JTextField.RIGHT、JTextField.LEADING、JTextField.TRAILING のいずれかを指定します。

コード1
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Test extends JFrame implements ActionListener {
	public static void main(String args[]) {
		JFrame win = new Test();
		win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		win.setBounds(10 , 10 , 400 , 300);
		win.show();
	}

	private JTextField text = new JTextField();
	private JLabel label = new JLabel();
	public Test() {
		text.addActionListener(this);

		getContentPane().add(text , BorderLayout.NORTH);
		getContentPane().add(label , BorderLayout.SOUTH);
	}

	public void actionPerformed(ActionEvent e) {
		label.setText("入力テキスト=" + text.getText());
	}
}
実行結果
コード1 実行結果

コード1はウィンドウの上部に JTextField コンポーネントを表示します。このコンポーネントにキーボードからテキストを入力し、Enter キーで入力を決定するとウィンドウ下部のラベルに入力されたテキストが表示されます。ActionListener を登録してリスナが呼び出されるタイミングで getText() メソッドから入力されたテキストを取得すれば、適切なタイミングで入力テキストを処理することができるのです。

8.1.2 キャレットと選択範囲

テキストコンポーネント内の、テキスト挿入位置を表す点滅している線のことをキャレットと呼びます。キャレットは多くのシステムのテキスト入力コンポーネントで共通するものです。Windows などの近年のグラフィカルシステムでは、テキスト入力コンポーネント上で点滅する縦線として表示されますが、MS-DOS や UNIX のキャラクタユーザインタフェースなどでは点滅するアンダーラインとしてキャレットが表現されています。

JTextComponent クラスは、このキャレットの描画も自由に拡張することができます。通常はデフォルトのキャレットで十分なので、特別な理由がない限りは拡張する必要はありません。キャレットは javax.swing.text.Caret インタフェースを実装しなければなりません。

表3 Caret インタフェースのメソッド
メソッド 解説
public void addChangeListener(ChangeListener l) キャレットの移動を常に追跡するリスナーを追加する。
public void removeChangeListener(ChangeListener l) キャレットの移動を追跡しているリスナーを削除する。
public boolean isVisible() キャレットが現在可視であるかどうかを判定する。
public void setVisible(boolean v) キャレットの可視または不可視を設定する。
public boolean isSelectionVisible() 選択範囲が現在も可視であるかどうかを判定する。
public void setSelectionVisible(boolean v) 選択範囲の可視または不可視を設定する。
public void setMagicCaretPosition(Point p) 現在のキャレット可視位置を設定する。
public Point getMagicCaretPosition() キャレットの現在の可視位置を返す。
public void setBlinkRate(int rate) キャレットの点滅間隔をミリ秒単位で設定する。
public int getBlinkRate() キャレットの点滅間隔をミリ秒単位で返す。
public int getDot() キャレットの現在の位置を取り出す。
public int getMark() マークの現在の位置を取り出す。
public void setDot(int dot) キャレットの位置を設定する。
public void moveDot(int dot) キャレットの位置 (ドット) を移動する。
public void install(JTextComponent c) JTextComponent のインタフェースに UI をインストールしている時に呼び出される。
public void deinstall(JTextComponent c) JTextComponent のインタフェースから UI を削除している時に呼び出される。
public void paint(Graphics g) キャレットを描画する。

キャレットで重要なプロパティは、ドットとマークでしょう。ドットは単純にキャレットの位置を表してると考えてください。マークは、基本的にドットと同じですが、選択範囲が定められている場合はドットとは反対側の位置を指しています。これらを制御すれば、キャレットの位置をインタフェースから変更することができます。

キャレットをコンポーネントに設定するには JTextComponent クラスの setCaret() メソッドを使います。現在設定されているキャレットは getCaret() メソッドから得ることができます。

JTextComponent クラス setCaret() メソッド
public void setCaret(Caret c)
JTextComponent クラス getCaret() メソッド
public Caret getCaret()

テキスト入力コンポーネントからキャレットを取得すれば、キャレットの点滅する間隔を設定することもできます。キャレットの位置の変更は、キャレットの addChangeListener() メソッドから ChangeListener を登録すれば監視することができるでしょう。

コード2
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.event.*;
import java.awt.*;

public class Test extends JFrame implements ChangeListener {
	public static void main(String args[]) {
		JFrame win = new Test();
		win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		win.setBounds(10 , 10 , 400 , 300);
		win.show();
	}

	private JTextField text = new JTextField();
	private JLabel label = new JLabel();
	public Test() {
		Caret caret = text.getCaret();
		caret.setBlinkRate(100);
		caret.addChangeListener(this);

		getContentPane().add(text , BorderLayout.NORTH);
		getContentPane().add(label , BorderLayout.SOUTH);
	}

	public void stateChanged(ChangeEvent e) {
		Caret caret = text.getCaret();
		label.setText("dot=" + caret.getDot() + ",mark=" + caret.getMark());
	}
}
実行結果
コード1 実行結果

コード2は、JTextField オブジェクトから getCaret() メソッドを使って設定されているキャレットを取得し、点滅間隔を 100 ミリ秒に設定しています。そのため、コンポーネントを表示するとデフォルトよりもキャレットの点滅が高速であることを確認できます。

また、キャレットに ChangeListener を登録しているため、キャレットの設定が変更されるたびに stateChanged() メソッドが呼び出されます。ユーザーが入力する位置をマウスやキーボードの方向キーで変更すると、キャレットのドットやマークが変更されリスナが呼び出されます。リスナが呼び出されると、ウィンドウ下部のラベルにキャレットのドットとマークが表示されます。実行結果を見ると、選択範囲が設定されてる場合はドットとマークの値がことなることを確認できます。

因みに、選択範囲を描画しているのはハイライタと呼ばれる javax.swing.text.Highlighter インタフェースを実装するオブジェクトです。 デフォルトでは単一色で選択範囲を塗りつぶしていますが、このインタフェースを独自実装することで選択範囲の表現方法を変更することもできます。新たには依頼他を設定するには JTextComponent クラスの setHighlighter() メソッドを、現在のハイライタを取得するには getHighlighter() メソッドを使います。

JTextComponent クラス setHighlighter() メソッド
public void setHighlighter(Highlighter h)
JTextComponent クラス getHighlighter() メソッド
public Highlighter getHighlighter()

通常は、ハイライタを独自に実装する必要はありません。キャレットやハイライタは独自実装しなくても、JTextComponent から色を選択することができます。キャレットやハイライタの形状を特殊な形に変えたい場合を除けば、デフォルトのキャレットとハイライタで必要な処理はすべて実現できます。キャラットと選択範囲の色に関する JTextComponent クラスのメソッドは表4に示します。

表4
メソッド 解説
public void setCaretColor(Color c)

キャレットを描画するのに使う現在の色を設定する。

public Color getCaretColor() キャレットを描画するのに使う現在の色を返す。
public void setSelectionColor(Color c) 選択領域を描画するのに使う現在の色を設定する。
public Color getSelectionColor() 選択領域を描画するのに使う現在の色を返す。
public void setSelectedTextColor(Color c) 選択したテキストを描画するのに使う現在の色を設定する。
public Color getSelectedTextColor() 選択したテキストを描画するのに使う現在の色を返す。

これらのメソッドを使えば、テキスト入力コンポーネントに表示されるキャレットや、選択範囲で塗りつぶされる色を変更することができます。コンポーネントの前景色や背景色を変更すると、キャレットや選択範囲の色と重なってしまうことがあるので、こうしたメソッドで選択範囲やキャレットを強調できる色に変更します。

コード3
import javax.swing.*;
import java.awt.*;

public class Test extends JFrame {
	public static void main(String args[]) {
		JTextField text = new JTextField();
		text.setFont(new Font("Serif" , Font.PLAIN , 30));
		text.setSelectedTextColor(Color.BLUE);
		text.setSelectionColor(new Color(0xFF , 0xD0 , 0xD0));
		text.setCaretColor(Color.RED);

		JFrame win = new Test();
		win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		win.setBounds(10 , 10 , 400 , 300);
		win.getContentPane().add(text , BorderLayout.NORTH);
		win.show();
	}
}
実行結果
コード3 実行結果

コード3は、JTextField オブジェクトのキャレットや選択範囲の色を変更して表示しています。キャレットには赤、選択範囲には薄いピンク、そして、選択範囲内のテキストは青く表示するように指定しています。