JavaFX チュートリアル〜今度こそ、初めてでも大丈夫4:RadioButton〜

イントロダクション

以前記載した記事で「初めてでも大丈夫」などと記載していましたが、ちょっと「危ういな」と思いチュートリアルをやってみようとなりました。

今回はラジオボタンの表示をやります。

チュートリアル

ここのページを、戦国Xサラの要領でガンガン斬り伏せながらやっていきます。

<チュートリアル>

基本のコード(ちょっとダメなコード)

public class Lv3_RadioButton extends Application {

    /**
     * このメソッドは、Applicationクラス(JavaFXのフレームワーク部品)
     * のメソッドをオーバーライドする。
     * {@link Application#launch(String...)}から呼び出される。
     */
    @Override
    public void start(Stage primaryStage) throws Exception {
        // チュートリアルには省略されている部分
        Group group = new Group();
        // この部分がチュートリアルに記載されている。
        //A radio button with an empty string for its label
        RadioButton rb1 = new RadioButton();
        //Setting a text label
        rb1.setText("Home");
        //A radio button with the specified label
        RadioButton rb2 = new RadioButton("Calendar");

        // 上のコンポーネント(Labelとか、イメージとか)
        group.getChildren().addAll(rb1, rb2);
        // チュートリアルでは省略されている
        Scene scene = new Scene(group, 300, 300);
        primaryStage.setScene(scene);
        primaryStage.setTitle("チュートリアル1");
        primaryStage.show();
    }

    /**
     * メインメソッド。
     * Apllicationクラスのlaunchメソッドを呼び出す。
     * 
     * @param args プログラム引数
     */
    public static void main(String[] args) {
        launch(args);
    }
}

今回は、ちょっとダメなコードを基本にしていきます。なんでダメなのかは実行結果を見れば一目瞭然。。。

コンポーネントが重なってしまい、意味がわかりません。

ここで、start()メソッドの初めの部分で「Group group = new Group();」というコードがありますが、この部品をGroupからVBoxへ変更します。

Groupはレイアウトクラスですが、VBoxの親の親。。。とちょっと遠い親戚な関係です。下のJavaDocをみてください。

こんな感じでクラスの系譜がちょっと違うのです。コンポーネントを配置するコンテナクラスという意味で「レイアウトクラス」という文言を使いましたが、とりあえずは「VBoxも Groupもコンポーネントを保持するんだな」と理解してくれればOK!

そして、以下の様にVBoxをGroupの代わりに使用してみると。。。

こんな感じで表示されます。

そしてコードはこんな感じになりました。これもイマイチ。。。Gitからダウンロード

public void start(Stage primaryStage) throws Exception {
    // チュートリアルには省略されている部分
    VBox group = new VBox(20b);
    // この部分がチュートリアルに記載されている。

    //A radio button with an empty string for its label
    RadioButton rb1 = new RadioButton();
    //Setting a text label
    rb1.setText("Home");
    rb1.setSelected(true);
    group.getChildren().add(rb1);

    //A radio button with the specified label
    RadioButton rb2 = new RadioButton("Calendar");
    rb2.setToggleGroup(togle);
    group.getChildren().add(rb2);

    RadioButton rb = new RadioButton("Agree");
    group.getChildren().add(rb);

    // 上のコンポーネント(Labelとか、イメージとか)
    group.getChildren().addAll(rb1, rb2, rb);
    // チュートリアルでは省略されている
    Scene scene = new Scene(group, 300, 300);
    primaryStage.setScene(scene);
    primaryStage.setTitle("チュートリアル3");
    primaryStage.show();
}

これで、3つあるラジオボタンの1つを選択するとそれのみを選択する様になります。選択することができます。表示結果は下の様になります、

これでは味気ないので次の様な機能を実装しようと思います。

  1. 初期表示時には「家の画像」を表示する
  2. ラジオボタンで選択すると選択した画像を表示する

それぞれ、Home, Calender, Agreeで以下の様な画像です。

Home
Calender
Agree

ちょっとややこしくなってしまいました。。。

<ソースコード>

@Override
public void start(Stage primaryStage) throws Exception {
    // チュートリアルには省略されているものから変更
    // 横のレイアウト
    HBox lineLayout = new HBox();
    // 縦のレイアウト
    VBox group = new VBox(20d);
    // 横のレイアウトに追加
    lineLayout.getChildren().add(group);

    /* トグル・グループの追加
     * トグルが設定されているラジオボタンは
     * 1つのグループとして扱われる
     */
    final ToggleGroup togle = new ToggleGroup();
    //A radio button with an empty string for its label
    RadioButton rb1 = new RadioButton();
    //Setting a text label
    rb1.setText("Home");
    rb1.setToggleGroup(togle);
    rb1.setSelected(true);
    // イベント用UserData
    rb1.setUserData("home");
    // 縦のレイアウトに追加
    group.getChildren().add(rb1);
    //A radio button with the specified label
    RadioButton rb2 = new RadioButton("Calendar");
    rb2.setToggleGroup(togle);
    // イベント用UserData
    rb2.setUserData("calendar");
    // 縦のレイアウトに追加
    group.getChildren().add(rb2);

    RadioButton rb = new RadioButton("Agree");
    // イベント用UserData
    rb.setUserData("contacts");
    // サイズを合わせる
    rb.setToggleGroup(togle);
    // 縦のレイアウトに追加
    group.getChildren().add(rb);

    // 横のレイアウトに追加
    ImageView imageView = new ImageView();
    lineLayout.getChildren().add(imageView);
    final Map<String, Image> imageMap = createImageMap(imageView);

    // イベント処理
    togle.selectedToggleProperty().addListener(
            (ObservableValue<? extends Toggle> ov, Toggle old_toggle, Toggle new_toggle) ->{
                if (togle.getSelectedToggle() != null) {
                    String userData = togle.getSelectedToggle().getUserData().toString();
                    imageView.setImage(imageMap.get(userData));
                }
            });
    // 上のコンポーネント(Labelとか、イメージとか)
    // チュートリアルでは省略されている
    Scene scene = new Scene(lineLayout, 1000, 300);
    primaryStage.setScene(scene);
    primaryStage.setTitle("チュートリアル3");
    primaryStage.show();
}

実行結果

上から順番に、

// 横のレイアウト
HBox lineLayout = new HBox();
// 縦のレイアウト
VBox group = new VBox(20d);
// 横のレイアウトに追加
lineLayout.getChildren().add(group);
  1. 横と縦のレイアウトを用意する。
  2. 縦のレイアウトは20d(double型の20)分の間隔をあけてやる。
  3. 横のレイアウトに縦のレウアウトを追加

イメージは下の様な感じです。

でわでわ。。。

投稿者:

takunoji

音響、イベント会場設営業界からIT業界へ転身。現在はJava屋としてサラリーマンをやっている。自称ガテン系プログラマー(笑) Javaプログラミングを布教したい、ラスパイとJavaの相性が良いことに気が付く。 Spring framework, Struts, Seaser, Hibernate, Playframework, JavaEE6, JavaEE7などの現場経験あり。 SQL, VBA, PL/SQL, コマンドプロント, Shellなどもやります。

コメントを残す