このドキュメントでは、書式付きテキスト・フィールドの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
に変更。