JSpinner
- 単純なシーケンスコンテナこのドキュメントでは、新しい Swing コンポーネントである JSpinner について説明します。
もっとも多く作成の要求があった Swing コンポーネントの 1 つに、スピナがあります。これは、ユーザが順序付けられた集合から数値またはオブジェクトを選択できるようにする単一行の入力フィールドです。 スピナには通常、選択可能な値を段階的に表示するための一組の小さな矢印型ボタンが提供され、上向きと下向きの矢印キーでも値を循環して表示できます。 ユーザは、有効な値をスピナに直接入力することもできます。 コンボボックスにも似たような機能がありますが、重要なデータがわかりにくくなる可能性のあるドロップダウンリストを必要としないスピナのほうが、ときには好まれます。
この変更に対応するバグ追跡レポートは、 4290529 です。
スピナは、最近の GUI で一般的なものです。 以下に、いくつかの一般的な Look & Feel と OpenWindows からの例を示します。
Windows | CDE/Motif | JLF | Mac Aqua | OpenWindows |
これらのスピナはすべて、非常に単純な動作を行います。 スピナにフォーカスがあるときに矢印ボタンをクリックすると、フィールドの値が変わります。キーボードの上向き矢印キーと下向き矢印キーでも同じ結果になります。 アプリケーションによっては、スピナの値が上限または下限に達すると、上向きまたは下向き矢印ボタンが無効になったり、その値が反対の極限値にリセットされたりします。
JSpinner
、SpinnerModel
、SpinnerListModel
JSpinner
クラスは、3 つの子を管理する単純な Swing コンテナです。子とは、2 つの矢印ボタンと、スピナの値を表示するための「エディタ」と呼ばれる 1 つのコンポーネントです。 スピナに表示される値は、 SpinnerModel
と呼ばれるオブジェクトのシーケンスから構成されるモデルによってカプセル化されます。
public interface SpinnerModel { Object getValue(); void setValue(Object); Object getNextValue(); Object getPreviousValue(); void addChangeListener(ChangeListener x); void removeChangeListener(ChangeListener x);}
SpinnerModel
インタフェースは、ListModel
と似ており、両方とも値のシーケンスを表現しますが、重要な相違点がいくつかあります。
SpinnerModel
のモデルは、一連の要素へのランダムなアクセスはサポートしない。 「現在」、「次」、および「前」という、並んでいる 3 つの値にだけ、一度にアクセスできる。
size
メソッドからシーケンスの長さは返されない。
SpinnerModel
モデルの値のプロパティは読み取り/書き込み両用であり、読み取り専用の ListModels
シーケンスの要素とは異なる。 この違いが、JList
と JSpinner
の役割の違いを反映している。 前者はリストからの 1 つ以上の項目の「選択」を単純化するために設計されたのに対し、後者は単一の値を直接入力するために設計された。
JSpinner
とそのモデルとの関係は単純です。 エディタコンポーネントは ChangeListener
経由でモデルを監視し、SpinnerModel.getValue()
によって返されたオブジェクトを常に表示します。 上向きおよび下向きの矢印ボタンは、それぞれ setValue(getNextValue())
または setValue(getPreviousValue())
を呼び出すことで値を更新します。 シーケンスの最後または先頭に達したときに getNextValue
および getPreviousValue
メソッドは null
を返すので、矢印ボタンのアクションでは、モデルの値を更新する前に null
をチェックする必要があります。 エディタがある種の書き込み可能なフィールドの場合は、モデルに定義された制約を尊重すること、または無効な値に対して setValue
によってスローされた IllegalArgumentException
を処理することが、エディタの役割になります。
SpinnerListModel
では、java.util.List
およびオブジェクト配列という、2 つの一般的な可変のシーケンス型がサポートされます。 デフォルトのロケールでユーザが曜日を選択できるようにする JSpinner
を作成する例は、次のようになります。
String[] days = new DateFormatSymbols().getWeekdays(); SpinnerModel model = new SpinnerListModel(days); JSpinner spinner = new JSpinner(model);
スピナの model
プロパティを初期化することに加えて、これらのコンストラクタが、SpinnerModel
の value
を表示するエディタコンポーネントを作成します。また、コンストラクタを使用して value
を変更できます。 デフォルトでは、このために protected JSpinner.createEditor
メソッドが使用され、このメソッドが、モデルを表示するために構成された JFormattedTextField
を作成します。
スピナの現在値を検出または初期化するには、モデルの value
プロパティを使用するか、または、モデルに委譲されたばかりの、便利な JSpinner
value
プロパティを使用することができます。 たとえば、上の例で構成されたスピナを使用すると、次の 2 つの文は同等です。
String selectedDay = spinner.getModel().getValue().toString(); String selectedDay = spinner.getValue().toString();
スピナの値の設定は似ています。 モデルがサポートしないオブジェクトに SpinnerModel
の値を設定しようとすると、IllegalArgumentException
がスローされます。
日付と数値は、スピナのコンポーネントにもっとも一般的に適用される 2つです。 これらの型のスピナ化を単純にするために、SpinnerDateModel
と SpinnerNumberModel
の、2 つの SpinnerModel
実装クラスが追加されました。
SpinnerDateModel
スピナのもっとも一般的な使用法の 1 つが、編集可能な日付をコンパクトに提示することです。 以下に、ユーザが完全に地域対応された日付を入力できる JSpinner
の作成例を示します。
SpinnerDateModel model = new SpinnerDateModel(); JSpinner spinner = new JSpinner(model); Date value = model.getDate();
この例で、JSpinner
コンストラクタは、日付を編集する JFormattedTextField
エディタを作成し、ChangeListener
を SpinnerDateModel
に追加して、エディタとモデルの同期を保ちます。
ここで、 SpinnerDateModel
API を示します。 この API には、start
、end
、および stepSize
の 3 つの新しい読み取り/書き込み両用プロパティと、Date
にキャストする値を返す読み取り専用の date
プロパティが追加されました。
public class SpinnerDateModel extends AbstractSpinnerModel { public SpinnerDateModel(Date value, Comparable start, Comparable end, int stepSize) public SpinnerDateModel() public void setStart(Comparable start) public Comparable getStart() public void setEnd(Comparable end) public Comparable getEnd() public Object getNextValue() public Object getPreviousValue() public Date getDate() public Object getValue() public void setValue(Object value)}
startDate
および endDate
プロパティは、上限または下限がないことを示すために、null
になる可能性もあります。 引数を指定しない SpinnerDateModel
コンストラクタの場合は、開始日と終了日の両方を null
に初期化し、モデルの最初の日付は現在の日付です。
stepSize
プロパティの値は、Calendar
内でフィールドを指定する java.util.Calendar
定数の 1 つにする必要があります。 getNextValue
および getPreviousValue
メソッドは、stepSize
プロパティの値の分だけ日付を前方または後方に変更します。 たとえば、stepSize
が Calendar.DAY_OF_WEEK
の場合は、nextValue
で現在の value
より 24 時間後の Date
を作成し、previousValue
で 24 時間前の Date
を作成します。
stepSize
に有効な値は、次のとおりです。
Calendar.ERA
Calendar.YEAR
Calendar.MONTH
Calendar.WEEK_OF_YEAR
Calendar.WEEK_OF_MONTH
Calendar.DAY_OF_MONTH
Calendar.DAY_OF_YEAR
Calendar.DAY_OF_WEEK
Calendar.DAY_OF_WEEK_IN_MONTH
Calendar.AM_PM
Calendar.HOUR
Calendar.HOUR_OF_DAY
Calendar.MINUTE
Calendar.SECOND
Calendar.MILLISECOND
デフォルトの SpinnerDateModel
editor
は、テキストのカーソル位置に基づいて stepSize
プロパティを調節します。 たとえば、カーソルがエディタの month サブフィールドに移動した場合は、incrementSize
が Calendar.DAY_OF_MONTH
に変更されます。
スピナはしばしば、気温から株価までのあらゆる数値を表す、編集可能な整数および実数を提示するために使用されます。 SpinnerNumberModel
では、Byte
から Double
までの基本的なすべての Java の Number
型を基本的にサポートします。
初期値を 500.0 にして、0.0 から 1000.0 の間で 1/8 の実数の倍数をユーザが選択できるようにするスピナを作成するには、次のようにコーディングします。
SpinnerNumberModel model = new SpinnerNumberModel(500.0, 0.0, 1000.0, 0.625); JSpinner spinner = new JSpinner(model); double value = model.getNumber().doubleValue();
この例で、JSpinner
コンストラクタは、実数を編集するための JFormattedTextField
エディタを作成し、ChangeListener
を SpinnerDateModel
に追加して、エディタとモデルの同期を保っています。
ここで、SpinnerNumberModel
API について簡単にまとめます。 この API には、minimum
、maximum
、および stepSize
の 3 つの新しい読み取り/書き込み両用プロパティと、Number
にキャストする値を返す読み取り専用の number
プロパティが追加されました。
public class SpinnerNumberModel extends AbstractSpinnerModel { public SpinnerNumberModel(Number value, Comparable minimum, Comparable maximum, Number stepSize) public SpinnerNumberModel(int value, int minimum, int maximum, int stepSize) public SpinnerNumberModel(double value, double minimum, double maximum, double stepSize) public SpinnerNumberModel() public void setMinimum(Comparable minimum) public Comparable getMinimum() public void setMaximum(Comparable maximum) public Comparable getMaximum() public void setStepSize(Number stepSize) public Number getStepSize() public Object getNextValue() public Object getPreviousValue() public Number getNumber() public Object getValue() public void setValue(Object value)}
SpinnerDateModel
に関しては、minimum
および maximum
プロパティが、それより大きな値または小さな値がないことを示すために、null
になる可能性もあります。 stepSize
プロパティには、nextValue
または previousValue
を計算するために value
と加算または減算する値を指定します。
スピナのサポートにあたって、次の 6 つのクラスと 1 つのインタフェース (SpinnerModel
) が javax.swing
パッケージに追加されました。
また、SpinnerUI
が javax.swing.plaf
パッケージに、BasicSpinnerUI
が javax.swing.plaf.basic
パッケージに追加されました。