このドキュメントでは、書式付きテキスト・フィールドの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用のセッター/ゲッターがあり、必要に応じてDocumentFilterをサポートできるように、AbstractDocumentから派生しないDocumentのためのプロパティが設定されます)。 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の書式を設定し、Stringを取るコンストラクタを使用してObjectを作成します。 DefaultFormatterでは、いくつかの構成オプションを使用できます。
|
オプション |
説明 |
|---|---|
| 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に変更。