Go to Previous Page Go to Contents Go to Java Page Go to Next Page
New Features of Java2 SDK, Standard Edition, v1.4
 
 

Spinner

 
 

新しいコンポーネント

 
 

スピナは Java2 SE, v1.4 で新しくできた Swing コンポーネントです。

Windows のユーザだと、下図のような時間を設定するダイアログを見たことありますよね。

Configuration Dialog for Date/Time
図 1 日付と時刻のプロパティ設定ダイアログ

 

この図の中で赤丸で示した部分がスピナです。

今までこれと同じようなコンポーネントを Swing で作ろうとしたら、JTextField と 2 つの JButton を組み合わせて作るしかありませんでしたが、スピナができたので簡単に作れるようになりました。でも、Visual Basic や Visual C++ では使えて当然だったのですから、やっと追いついたという感じですね。

 

 
  なにはともあれ使ってみる  
 

使い方は簡単です。なにも考えずに使ってみた例が SpinnerTest1.java です。

Applet の HTML SpinnerTest1.html
Applet のソース SpinnerTest1.java

スピナは Swing では JSpinner というクラスになります。SpinnerTest1 は JSpinner オブジェクトを引数なしで生成して、Applet に貼ってみただけです。

public class SpinnerTest1 extends JApplet {

    public void init(){
        // Spinner の生成
        JSpinner spinner = new JSpinner();
        getContentPane().add(spinner);
    }
}

JSpinner クラスは引数なしのコンストラクタでオブジェクトを生成すると、数字が編集できて初期値が 0 のスピナを生成します。

数字以外のものや、初期値が 0 以外の場合は、JSpinner オブジェクトを生成するときに指定しなければいけません。そのときの指定の方法ですが、モデルを用意します。

Swing ではコンポーネントが表示する情報はモデルが持っています。例えば、JTable クラスであれば TableModel クラスになります。同じように JSpinner クラスも SpinnerModel クラスで表示する情報を保持させます。

モデルには表示する情報の違いにより 3 種類用意されています。

クラス 表示する情報
SpinnerNumberModel 数字
SpinnerListModel リスト
SpinnerDateModel 日づけ

この 3 種類のモデルを使ってみたのが SpinnerTest2.java です。

Applet の HTML SpinnerTest2.html
Applet のソース SpinnerTest2.java

SpinnerTest2 では 3 つのスピナを作っています。それぞれ makeNumberSpinner メソッド、makeListSpinner メソッド、makeDateSpinner メソッドで生成しています。

 1:    private JSpinner makeNumberSpinner(){
 2:        // 初期値 50, 最小 10, 最大 100, ステップ 10 のモデル
 3:        SpinnerNumberModel model = new SpinnerNumberModel(50, 10, 100, 10);
 4:        return new JSpinner(model);
 5:    }
 6: 
 7:    private JSpinner makeListSpinner(){
 8:        // Spinner の選択肢を準備
 9:        java.util.List list = new ArrayList();
10:        list.add("A");
11:        list.add("B");
12:        list.add("C");
13:        list.add("D");
14:        list.add("E");
15:
16:        SpinnerListModel model = new SpinnerListModel(list);
17:        return new JSpinner(model);
18:    }
19: 
20:    private JSpinner makeDateSpinner(){
21:        // 初期値 現在時刻, 最小・最大 指定せず, 分が変更可能
22:        SpinnerDateModel model = new SpinnerDateModel(new Date(),
23:                                      null, null, Calendar.MINUTE);
24:        return new JSpinner(model);
25:    }

赤色で示したところが、モデルを生成している部分です。JSpinner でモデルを指定する場合は、モデルを引数にして生成します(4, 17, 24 行目。

3 行目では数字を表す SpinnerNumberModel オブジェクトを生成しています。引数は順に初期値、最小値、最大値、ステップで引数の型は int となります。ですから、ここでは

  • 初期値 50
  • 最小値 10
  • 最大値 100
  • ステップ 10

となりモデルを生成しています。

SpinnerNumberModel は int 型以外にも double 型、Number 型のコンストラクタがありますが、引数の順番と意味は int 型のときと同じです。

次が SpinnerListModel クラスです。SpinnerListModel クラスははじめから選択肢を決めておきます。9 行目から 14 行目が選択肢を作っている部分です。作成した List オブジェクトの選択肢を引数として SpinnerListModel オブジェクトを生成します (16 行目)。

SpinnerListModel クラスは List クラス以外に Object[] (Object 型の配列) を引数にとるコンストラクタもあります。

最後が日づけを表す SpinnerDateModel クラスです。

SpinnerDateModel クラスのコンストラクタは初期値、開始日時、終了日時、編集できる部分を引数で指定します。開始日時と終了日時を指定しない場合は null にしておきます。

最後の編集できる部分ですが、ここには年、月、日などを指定するのですが、Calendar クラスの定数を利用します。使える定数は次のどれかです。

  • 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

23 行目では分を表す Calendar.MINUTE を指定しているので、分が編集可能になります。

 

 
 

見た目を変える

 
 

基本的な JSpinner クラスの使い方は分かりましたが、もう少しカスタマイズしてみましょう。

JSpinner が表示する情報をもっているのはモデルでしたが、表示に関してはエディタが担当します。SpinnerModel に対応する 3 つのエディタがあります。

クラス 対応するモデル
JSpinner.NumberEditor SpinnerNumberModel
JSpinner.ListEditor SpinnerListModel
JSpinner.DateEditor SpinnerDateModel

JSpinner.ListEditor はほとんどカスタマイズすることはできないので、それ以外の JSpinner.NumberEditor と JSpinner.DateEditor について行ってみましょう。

通常、数字を整形して出力する場合 java.text.DecimalFormat クラスを用います。JSpinner.NumberEditor クラスでは DecimalFormat クラスを内部的に呼び出しているので、DecimalFormat クラスで使用しているフォーマットを使うことができます。

同様に日にちを出力するときは、java.text.SimpleFormat クラスを使用します。JSpinner.DateEditor も SimpleFormat クラスのフォーマットを使用することができます。

これらのフォーマットを利用するにはエディタクラスのコンストラクタの引数で指定することで可能になります。整形した形で出力するようにしたのが SpinnerTest3.java です。

Applet の HTML SpinnerTest3.html
Applet のソース SpinnerTest3.java

エディターは第 1 引数に JSpinner オブジェクト、第 2 引数にフォーマットを指定します。エディタを JSpinner にセットするには setEditor メソッドを使用します。

    private JSpinner makeNumberSpinner(){
        SpinnerNumberModel model = new SpinnerNumberModel(0, -1000, 1000, 5);
        JSpinner spinner = new JSpinner(model);
 
        // 少なくとも 2 桁は必ず出力
        JSpinner.NumberEditor editor = new JSpinner.NumberEditor(spinner, "#,#00");
        spinner.setEditor(editor);
 
        return spinner;
    }

ここで使用しているフォーマット "#,#00" は、最低限 2 桁を出力して、3 桁目と 4 桁目の間にカンマを入れるようにするということを示しています。少なくとも、2 桁出力するので、0 や 5 の時でも、00, 05 と出力されます。また、1000 は 1,000 と出力されます。フォーマットの詳細は DecimalFormat クラスの JavaDoc をご覧ください。

    private JSpinner makeDateSpinner(){
        SpinnerDateModel model = new SpinnerDateModel(new Date(),
                                                      null, null, Calendar.MINUTE);
        JSpinner spinner = new JSpinner(model);
 
        // 西暦 2001.08.05 (日) 午前10:30:26 という形式 (Locale が日本の場合)
        // AC 2001.08.05 (Sunday) AM10:30:26 (Locale が US の場合)
        JSpinner.DateEditor editor = new JSpinner.DateEditor(spinner,
                                     "G yyyy.MM.dd (E) ahh:mm:ss");
        spinner.setEditor(editor);

        return spinner;
    }

日づけのフォーマットはロケールによって異なります。そのため、フォーマット指定してもロケールによって出力結果は異なります。例えば G は日本であれば "西暦"、アメリカだと "AC" と出力されます。フォーマットの詳細は SimpleDateFormat の JavaDoc を参照してください。

このようにエディタのフォーマットを指定したのですが、日にちの方はいまいちちゃんと動作してくれませんでした。一度 TextField にフォーカスすればちゃんとフォーマット通り出力されるのですが、なにもしないとデフォルトになってしまいます。

まだ、ベータ版なのでバグが残っているのかもしれません。正式版までには直ってほしいですね。

 

 
 

JSpinner のイベント

 
 

さて、次は JSpinner クラスのイベントです。

JSpinner クラスで発生するイベントは、値が変わったときに発生する javax.swing.event.ChangeEvent クラスです。ChangeEvent クラスに対応するリスナは javax.swing.event.ChangeListener インタフェースで、メソッドは stateChanged の 1 つだけです。

イベントも簡単なサンプルを作ってみました。

Applet の HTML SpinnerTest4.html
Applet のソース SpinnerTest4.java

JSpinner オブジェクトと JLabel オブジェクトを並べて、JSpinner オブジェクトの ChangeEvent が発生したら、JLabel オブジェクトの表示を更新させるという Applet です。

 1:    private JLabel label;
 2:    private JSpinner spinner;
 3:
 4:    public SpinnerTest4(){
 5:        spinner = makeNumberSpinner();
 6:        getContentPane().add(spinner, BorderLayout.CENTER);
 7: 
 8:        label = new JLabel(spinner.getValue().toString());
 9:        label.setBorder(new TitledBorder("Value"));
10:        getContentPane().add(label, BorderLayout.SOUTH);
11: 
12:        // spinner の値が変更されたら、label の値も変更する
13:        spinner.addChangeListener(new ChangeListener(){
14:            public void stateChanged(ChangeEvent event){
15:                label.setText(spinner.getValue().toString());
16:            }
17:        });
18:    }

JLabel オブジェクトの label と JSpinner オブジェクトの spinner は、Anonymous Class から使用できるようにプロパティにしました。

イベントのリスナ登録は 13 から 17 行目で行っています。リスナは Anonymous Class で、spinner から getValue メソッドで値を取得して、それを JLabel クラスの setText メソッドを使用して表示の更新を行っています (15 行目)。

JSpinner には値を取得するためのメソッド getValue 以外に、現在の値の次の選択肢を取得する getNextValue メソッド、同様に前の選択肢の getPreviousValue メソッドがあります。

今回使用したサンプルはここからダウンロードできます。

参考 URL

(Aug. 2001)

 
 
Go to Previous Page Go to Contents Go to Java Page Go to Next Page