JavaFXの主要コントロールを利用する

JavaFXにはさまざまなGUIコントロールが用意されている。その中でもよく使われる「チェックボックス」「ラジオボタン」「コンボボックス」「スライダー」について、基本的な使い方を見ていこう。

チェックボックス

JavaFXには多くのGUIコントロールが含まれている。それらを利用すれば、一般的なGUIを簡単に作成できる。ここでは基本的なGUIコントロールの簡単な使い方を整理する。

まずチェックボックスから説明する。これはjavafx.scene.controlパッケージのCheckBoxクラスとして用意されている。インスタンスは次のように作成する。

new Checkbox()
new Checkbox("表示テキスト")

引数にテキストを指定すると、そのテキストがチェックボックスの横に表示される。この表示テキストはButtonなどと同じようにsetTextでも設定できる。また、チェック状態は次のように扱える。

チェック状態を取得する。

boolean 変数 = checkbox.isSelected();

チェック状態を変更する。

checkbox.setSelected(boolean);

Checkboxにはアクションイベントを指定できる。チェックボックスをクリックするなどして選択状態が変更されると、アクションイベントが発生する。このイベント処理はButtonなどと同じようにsetOnActionメソッドで設定できる。

checkbox.setOnAction((ActionEvent) -> {
    // 実行する処理
});

ラムダ式を使うなら、このように書けばよい。これでチェック状態が変更されたときの処理を実行できる。

次はCheckBoxの簡単な使用例である。

package com.dekuma.javafx;
 
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
 
public class App extends Application {
    Label label;
    CheckBox check;
 
    public static void main(String[] args) {
        launch(args);
    }
 
    @Override
    public void start(Stage stage) throws Exception {
        label = new Label("This is JavaFX!");
        check = new CheckBox("체크박스");
        check.setSelected(true);
        check.setOnAction((ActionEvent)->{
            label.setText(check.isSelected() ? "Selected!" : "not selected...");
        });
         
        BorderPane pane = new BorderPane();
        pane.setTop(label);
        pane.setCenter(check);
        Scene scene = new Scene(pane, 320, 120);
        stage.setScene(scene);
        stage.show();
    }
 
}

実行するとチェックボックスが1つ表示され、それをクリックするとラベルに"Selected!“または"not selected …“と表示される。

ラジオボタン

ラジオボタンは、複数の項目の中から1つを選択するときによく使われるGUIである。これもjavafx.scene.controlパッケージに含まれている。RadioButtonというクラスを次のように作成する。

new RadioButton()
new RadioButton("表示テキスト")

チェックボックスと同じように、表示テキストはsetTextで変更できる。また、チェック状態はisSelectedsetSelectedメソッドで操作できる。クリック時の処理をアクションイベントで設定できる点も同じである。

表示テキストを取得する

String 変数 = radioButton.getText();

表示テキストを設定する

radioButton.setText(String);

チェック状態を取得する

boolean 変数 = radioButton.isSelected();

チェック状態を変更する

radioButton.setSelected("boolean");

アクションイベントを設定する

radioButton.setOnAction((ActionEvent) -> {
    // 実行する処理
});

ラジオボタンとチェックボックスは非常によく似ており、基本的な使い方はほぼ同じである。チェックボックスが使えるなら、ラジオボタンの基本もほぼ理解できるだろう。

しかし、これだけではまだラジオボタンを正しく使うことはできない。「グループ化」の仕組みを理解する必要がある。

ToggleGroup

ラジオボタンがチェックボックスと異なるのは、複数のコントロールをまとめて扱う点である。単にインスタンスを作っただけでは「クリックすると選択されるボタン」にすぎない。ラジオボタンは複数のボタンがグループとして機能し、その中で常に1つだけが選択されるようにする必要がある。

そこでToggleGroupというクラスを利用する。これはjavafx.scene.controlパッケージにあり、名前のとおりON/OFFする複数のコントロールを1つのグループとして管理する機能を提供する。インスタンスは次のように作成する。

new ToggleGroup()

引数などは必要ない。RadioButtonには、ラジオボタンが属するグループを設定するメソッドが用意されているので、そこにToggleGroupを設定する。

radioButton.setToggleGroup(ToggleGroup);

複数のRadioButtonに同じToggleGroupを設定すると、それらは1つのグループになり、クリックされたラジオボタンだけが選択される。

次はToggleGroupの簡単な使用例である。

package com.devkuma.javafx;
 
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.RadioButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;
 
public class App extends Application {
    Label label;
    ToggleGroup group;
 
    public static void main(String[] args) {
        launch(args);
    }
 
    @Override
    public void start(Stage stage) throws Exception {
        label = new Label("This is JavaFX!");
        group = new ToggleGroup();
        RadioButton btn1 = new RadioButton("Male");
        btn1.setToggleGroup(group);
        btn1.setSelected(true);
        RadioButton btn2 = new RadioButton("Female");
        btn2.setToggleGroup(group);
        btn1.setOnAction((ActionEvent)->{
            label.setText("you are Male?");
        });
        btn2.setOnAction((ActionEvent)->{
            label.setText("you are Female?");
        });
         
        BorderPane pane = new BorderPane();
        pane.setTop(label);
        FlowPane flow = new FlowPane();
        flow.getChildren().add(btn1);
        flow.getChildren().add(btn2);
        pane.setCenter(flow);
        Scene scene = new Scene(pane, 320, 120);
        stage.setScene(scene);
        stage.show();
    }
 
}

ここでは2つのRadioButtonを作成し、同じToggleGroupを設定している。常にクリックしたラジオボタンだけが選択されることがわかる。

コンボボックス

複数の項目から1つを選択するGUIはいくつかある。その代表が「コンボボックス」である。これはjavafx.scene.controlパッケージのComboBoxというクラスとして用意されている。

new ComboBox()
new ComboBox("表示内容")

コンボボックスは、ドロップダウンメニューのように項目を表示する。メニューに表示する内容はあらかじめ設定しておく必要がある。new ComboBoxの引数に表示内容を渡すと、その内容がメニューとして表示される。

問題は「表示内容をどのように用意するか」である。これはjavafx.collectionsパッケージのObservableListインスタンスとして用意する必要がある。

このインスタンスの作成方法はいくつかあるが、もっともわかりやすいのはjavafx.collectionsパッケージのFXCollectionsクラスにあるメソッドを利用する方法である。

ObservableList 変数 = FXCollections.observableArrayList(値1, 値2, ...);

このようにしてObservableListインスタンスを作成できる。引数にはメニューに表示する値を指定する。もっとも一般的なのはString値を指定して表示する方法である。ObservableListで表すなら次のようになる。

ObservableList<String> 変数 = FXCollections.observableArrayList(...);

このようにインスタンスを作成し、それをnew ComboBoxの引数として渡せばよい。

ComboBoxから取得する値

このように設定された値は、ComboBoxで選択されると次のように取得できる。

Object 変数 = comboBox.getValue();

getTextなどではなくgetValueである点に注意しよう。取り出すのはテキストではなく、選択されたオブジェクトである。ObservableList<String>としてデータを用意している場合はStringが取得される。別の例として、ObservableList<Integer>でデータを設定していればIntegerが取得される。

編集可能設定

また、ComboBoxは直接テキストを入力できるように設定することもできる。これにはsetEditableメソッドを使う。

comboBox.setEditable(boolean);

これをtrueに設定すると編集可能になり、メニューを選択するだけでなく直接テキストを入力できる。直接入力の場合、getValueで取得できるものはStringである。表示データにString以外の値を設定している場合は、メニュー選択とテキスト入力でgetValueから返るインスタンスの型が異なる可能性がある点に注意しよう。

次はComboBoxの簡単な使用例である。

package com.devkuma.javafx;
 
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;
 
public class App extends Application {
    Label label;
    ComboBox<String> combo;
     
    public static void main(String[] args) {
        launch(args);
    }
 
    @Override
    public void start(Stage stage) throws Exception {
        label = new Label("This is JavaFX!");
        ObservableList<String> data = FXCollections.observableArrayList("One", "Two","Three");
        combo = new ComboBox<String>(data);
        combo.setOnAction((ActionEvent)->{
            label.setText(combo.getValue());
        });
        BorderPane pane = new BorderPane();
        pane.setTop(label);
        pane.setCenter(combo);
        Scene scene = new Scene(pane, 320, 120);
        stage.setScene(scene);
        stage.show();
    }
 
}

ComboBoxで項目を選択すると、それがLabelに表示される。ComboBoxsetOnActionでアクションイベント処理を設定できるため、これを利用して処理している。

スライダー

アナログ的に「ここからここまでの値」を入力するために使われるのが「スライダー」である。スライダーは、マウスでバーのノブをドラッグして値を設定する。これはjavafx.scene.controlパッケージのSliderというクラスとして用意されている。

new Slider()
new Slider(最小値, 最大値, 現在値)

引数なしで作成すると、デフォルト状態のインスタンスが作成される。引数に最小値、最大値、現在値をそれぞれdoubleで指定すると、指定された範囲内で値を選択できる。

このSliderには表示に関する細かなプロパティがあり、それらを設定することで表示方法をさまざまに調整できる。

表示方向を設定する

slider.setOrientation(Orientation);

これは縦方向か横方向かを設定するものである。引数にはjavafx.geometryパッケージのOrientationクラスのフィールドを指定する。このクラスには次の2つのクラスフィールドが含まれている。

  • HORIZONTAL: 横方向を表す値。
  • VERTICAL: 縦方向を表す値。

目盛り表示をON/OFFする

slider.setShowTickMarks(boolean);
slider.setShowTickLabels(boolean);

スライダーには数値の目盛りを表示できる。setShowTickMarksは目盛りの表示を設定するもので、trueにすると目盛りが表示される。また、setShowTickLabelsは目盛り内に最小値や最大値のような値を表示する。

値を目盛りにスナップする

slider.setSnapToTicks(boolean);

設定値がtrueの場合、ドラッグしたときの値が表示されている目盛り位置に強制的にそろえられる。falseの場合はドラッグに制限がなくなり、値は細かな実数値として取得できる。

値を操作する

double  = slider.getValue();
slider.setValue(double);

Sliderの値はgetValuesetValueで操作できる。取得される値は実数である。

簡単な使用例は次のとおりである。

package com.devkuma.javafx;
 
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
 
public class App extends Application {
    Label label;
    Slider slider;
    Button button;
     
    public static void main(String[] args) {
        launch(args);
    }
 
    @Override
    public void start(Stage stage) throws Exception {
        label = new Label("This is JavaFX!");
        slider = new Slider(0, 100, 50);
        slider.setShowTickMarks(true);
        slider.setShowTickLabels(true);
        slider.setSnapToTicks(true);
        button = new Button("CLICK");
        button.setOnAction((ActionEvent)->{
            label.setText("VALUE: " + slider.getValue());
        });
        BorderPane pane = new BorderPane();
        pane.setTop(label);
        pane.setCenter(slider);
        pane.setBottom(button);
        Scene scene = new Scene(pane, 320, 120);
        stage.setScene(scene);
        stage.show();
    }
 
}

ドラッグして適当な値を設定し、ボタンをクリックすると現在値が表示される。別のボタンを用意しているのは、Sliderクラスがアクションイベントをサポートしていないためである。

ただし、それ以外のイベントは用意されており、それらを利用して操作時の処理を実装できる。これについては改めて説明する。