このドキュメントでは、書式付きテキストフィールドの Swing での実装の概略を説明します。書式付きテキストフィールドによって、開発者は、テキストコンポーネントに入力できる正当な文字セットを指定できるようになります。このドキュメントは、以下の節で構成されています。
JFormattedTextField
によって、日付、数値、文字列および任意のオブジェクトの書式を設定することができます。JFormattedTextField
は、java.text.Format
クラスに基づいて、日付と数値に書式を設定します。現在のロケール固有の書式で日付を入力するための JFormattedTextField
を作成するには、次のようにします。
new JFormattedTextField(new Date());
特定の書式で日付を表示することが必要な場合は、SimpleDateFormat
コンストラクタの 1 つを使用できます。
new JFormattedTextField(new SimpleDateFormat("MM/dd/yy"));
数値は、java.text.NumberFormat
のインスタンスによって処理されます。以下に、数値を編集する JFormattedTextField
を作成する方法をいくつか示します。
new JFormattedTextField(new Number(1000)); new JFormattedTextField(new DecimalFormat("#,###")); new JFormattedTextField(new DecimalFormat("0.###E0"));
JFormattedTextField
は、マスクが指定された文字列の編集もサポートします。このマスクで、指定した文字位置に置く有効な文字を指定します。米国の電話番号を編集する JFormattedTextField
を作成するには、次のコードを使用することができます。
new JFormattedTextField(new MaskFormatter("(###) ###-####"));
JFormattedTextField
自体は、そのスーパークラスである JTextField
の API のほかは、最小限の API を公開します。もっとも単純に説明すれば、JFormattedTextField
は、JTextField
に追加の Object 型の値のプロパティ、および書式を設定するオブジェクト (AbstractFormatter
のインスタンス) が付いたものと見なすことができます。
値のプロパティが Object
型であるため、開発者にとっては、JFormattedTextField
がどのように構成されたかに基づいて戻り値の型をキャストする必要があります。以下に、日付と JFormattedTextField
の使用法についての典型的なシナリオを示します。
JFormattedTextField ftf = new JFormattedTextField(); ftf.setValue(new Date()); ... Date date = (Date)ftf.getValue();
数値を編集する典型的なセッションは、次のようになります。
JFormattedTextField ftf = new JFormattedTextField(); ftf.setValue(new Integer(1000)); ... int intValue = ((Number)ftf.getValue()).intValue();
テキストコンポーネントにデータを入力するには、以前は Document
のサブクラスを作成することが必要でした。この作業は、単純で一般的な使用法としては、負荷が多い操作でした。この作業を簡略化するために、Document
にプラグインできる DocumentFilter
クラスが作成されました。Document
は、変更されなかったインタフェースです。代わりに、現在は AbstractDocument
に DocumentFilter
用のセッタ/ゲッタがあり、AbstractDocument
から派生しなかった Document
のためにプロパティが設定されるので、DocumentFilter
をサポートできます。DocumentFilter
付きの Document
がコンテンツを削除または挿入するようにメッセージを受け取ると、Document
は DocumentFilter
上でメッセージに応じたメソッドを呼び出します。操作を進行させる必要がある場合にコールバックを呼び出すことが、DocumentFilter
の役割になります。この方法で、DocumentFilter
が Document
を変更できる方法についての全体的な制御権を持ちます。DocumentFilter
は、次のようにして定義されます。
public void remove(FilterBypass fb, int offset, int length) throws BadLocationException; public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException; public void replace(FilterBypass fb, int offset, int length, String string, AttributeSet attr) throws BadLocationException;
DocumentFilter
が remove
または insertString
メソッドの内部から Document
を変更したい場合は、super
実装を呼び出すか、FilterBypass
上でそのメソッドを呼び出す必要があります。super
または FilterBypass
上でメソッドを呼び出すと、フィルタを迂回する方法が提供されるので、呼び出し側はスタック再帰から抜け出せなくなることがありません。DocumentFilter
には、FilterBypass
上で 1 つだけメソッドを呼び戻すという制限はありません。FilterBypass
によって開示されたどのメソッドでも呼び出すことができ、DocumentFilter
のメソッドの 1 つの適用範囲内で必要なだけ何回でも呼び出すことができます。FilterBypass
は、次のようにして定義されます。
public abstract Document getDocument(); public abstract void remove(int offset, int length) throws BadLocationException; public abstract void insertString(int offset, String string, AttributeSet attr) throws BadLocationException; public abstract void replace(int offset, int length, String string, AttributeSet attr) throws BadLocationException;
次の例で、英小文字を英大文字にマッピングする DocumentFilter
を作成する方法を示します。
DocumentFilter upperDF = new DocumentFilter() { public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException { super.insertString(fb, offset, string.toUpperCase(), attr); } public void replace(FilterBypass fb, int offset, int length, String string, AttributeSet attr) throws BadLocationException { if (string != null) { string = text.toUpperCase(); } super.replace(fb, offset, length, string, attr); } };
DocumentFilter
と同様に、新規クラスの NavigationFilter
によって、選択範囲を置き換えることが可能な場所でフィルタリングを実行できるようになります。NavigationFilter
は、ある位置から選択範囲を設定する次の位置を決定するナビゲーション操作 (左、右、中央など) によって呼び出されます。NavigationFilter
は JTextComponent
のプロパティであり、次のように定義されています。
public void setDot(FilterBypass fb, int dot, Position.Bias bias); public void moveDot(FilterBypass fb, int dot, Position.Bias bias); public int getNextVisualPositionFrom(JTextComponent text, int pos, Position.Bias bias, int direction, Position.Bias[] biasRet) throws BadLocationException;
getNextVisualPositionFrom
は View
内に定義されており、一貫性を保つために、NavigationFilter
内のメソッドと同じ名前が付けられています。
DocumentFilter
と同様に、NavigationFilter
は、実際の変更を処理するために呼び出される FilterBypass
に渡されます。NavigationFilter.FilterBypass
は、次のように定義されています。
public abstract Caret getCaret(); public abstract void setDot(int dot, Position.Bias bias); public abstract void moveDot(int dot, Position.Bias bias);
前述したように、AbstractFormatter
のインスタンスは特定の Object 値の書式を設定するために使用されます。AbstractFormatter
は、DocumentFilter
を定義して編集ポリシーを指定したり、NavigationFilter
を定義してナビゲーションポリシーを指定したりすることもできます。AbstractFormatter
は、次のように定義されています。
public void install(JFormattedTextField ftf); public void uninstall(); public abstract Object stringToValue(String text) throws ParseException; public abstract String valueToString(Object value) throws ParseException; protected JFormattedTextField getFormattedTextField(); protected void setEditValid(boolean valid); protected void invalidEdit(); protected Action[] getActions(); protected DocumentFilter getDocumentFilter(); protected NavigationFilter getNavigationFilter();
JFormattedTextField
で AbstractFormatter
を使用する準備ができると、install
を呼び出します。AbstractFormatter.install
は、次の作業を実行します。
JFormattedTextField
のテキストを valueToString
の戻り値に設定します (ParseException
がスローされた場合は空の文字列が使用され、setEditValid(false)
が呼び出される)。
getDocumentFilter
から返された DocumentFilter
を JFormattedTextField
の Document
にインストールします。
getNavigationFilter
から返された NavigationFilter
を JFormattedTextField
にインストールします。
getActions
から返された Action
を JFormattedTextField
の ActionMap
にインストールします。
サブクラスで DocumentFilter
および NavigationFilter
の範囲を超えた追加の Listener
をインストールする必要がある場合は、サブクラスは install
をオーバーライドするだけか、または最初の位置にキャレットを配置することがあります。
ある種の AbstractFormatter
では、JFormattedTextField
が編集中に無効な値を含むことが許容されます。JFormattedTextField
で無効な値を含んでいることを示すことができるように、AbstractFormatter
は、ユーザが無効な値を入力したときに setEditValid(false)
を呼び出します。有効な値が入力されると、setEditValid(true)
が呼び出されます。
JFormattedTextField
が AbstractFormatter
で処理される場合は、uninstall
を呼び出します。uninstall
によって、以前にインストールされた Listener
が削除されます。
JFormattedTextField
は、AbstractFormatter
の作成を AbstractFormatterFactory
(JFormattedTextField
の公開されている static の内部クラス) のインスタンスに委譲します。この委譲によって、開発者がさまざまな状態の JFormattedTextField
に多様なフォーマッタを提供することが簡単になります。たとえば、現在の値が null
の場合は特殊な AbstractFormatter
、または編集中にはあるフォーマッタ、表示中には別のフォーマッタを提供することができます。AbstractFormatterFactory
は、次のように定義されています。
public abstract AbstractFormatter getFormatter(JFormattedTextField ftf);
開発者が AbstractFormatterFactory
を供給しなかった場合は、値の Class
に基づいたフォーマッタが作成されます。
DefaultFormatter
は JFormattedTextField.AbstractFormatter
を拡張します。これは、提供されたフォーマッタ実装のすべてに対応するスーパークラスです。DefaultFormatter
は toString
を使用して Object の書式を設定し、文字列をとるコンストラクタを使用して Object を作成します。DefaultFormatter
では、多数の構成オプションを使用できます。
Option |
説明 |
---|---|
CommitsOnValidEdit |
編集が JFormattedTextField に公開されて戻される時点を決定する。true の場合は、各編集が成功したあとに JFormattedTextField 上で commitEdit が呼び出される。そうでない場合は、Return キーが押されたときにだけ commitEdit が呼び出される
|
OverwriteMode |
文字を挿入するときの動作を構成する。overwriteMode が true の場合 (デフォルト) は、新しい文字が挿入されたときにモデル内の既存の文字がオーバーライドされる
|
AllowsInvalid | 編集中の値が無効であっても許容されるかどうかを決定する。確定が試行されるまでユーザが無効な値を入力できるようにしておくと、便利な場合が多い |
次の表に、使用されることを目的として提供する AbstractFormatter
の実装を示します。
AbstractFormatter |
オブジェクトの型 |
説明 |
---|---|---|
DefaultFormatter | オブジェクト |
valueToString が Object.toString() を使用し、stringToValue が文字列をとる単一引数のコンストラクタを使用する
|
MaskFormatter | 文字列 | 動作は、適切な値 (###-#### など) を指定する文字単位のマスクで示される |
InternationalFormatter | オブジェクト |
java.text.Format のインスタンスを使用して、valueToString および stringToValue を処理する
|
NumberFormatter | 数値 |
InternationalFormatter から派生した NumberFormat のインスタンスを使用して、書式を設定する
|
DateFormatter | 日付 |
InternationalFormatter から派生した DateFormat のインスタンスを使用して、書式を設定する
|
Swing では、java.text
パッケージ内の Format
クラスの拡張使用が可能な、書式付きの日付と数値がサポートされています。以前の API では、次のような問題点がありました。
format
を繰り返し呼び出す必要があった
Format
のサブクラスと競合する可能性が、潜在的にあった。DateFormat
と NumberFormat
の定数がすでに重なり合っているので、NumberFormat
では幸いなことに、YEAR_FIELD
が FRACTION_FIELD
として解釈されることに留意する。問題点が、多様な形式を持つ Format.format(Object, StringBuffer, FieldPosition)
メソッドの存在によって悪化した
MONTH_FIELD
用に NumberFormat
を要求した場合など (この例の実装では、開始インデックスと終了インデックスの両方に 0 が返された)
Format
のサブクラスでサポートされるかがわからなかった。書式付き文字列内ですべての文字がフィールドの一部ではないという事実に加え、このことが、すべてのフィールドを返す汎用メソッドの実装を不可能にした
これらの問題点は、以下のメソッドを java.text.Format
に追加することで、大幅に対処されました。
public AttributedCharacterIterator formatToCharacterIterator(Object obj);
各 Format
クラスでは、サポートする定数のために型保証された列挙を使用しています。
以下のクラスが 1.4 リリースでの新規クラスです。
この変更に関連するバグ追跡レポート: 4468474
次の定数の名前は、Java の命名規則に準拠するように変更されました。
CommitValueOnFocusLost
を COMMIT
に変更
CommitOrRevertValueOnFocusLost
を COMMIT_OR_REVERT
に変更
RevertValueOnFocusLost
を REVERT
に変更
PersistValueOnFocusLost
を PERSIST
に変更