前回 Eclipse4.4に JavaFX環境の設定手順を書きました。
今度は、Scene Builderを使ってFXMLを用いた JavaFXのプログラムを作ります。
作るプログラムは、
TextFieldに名前を入力し、ボタンをクリックすると ***さん こんにちは と表示する。
さらに簡単なメニューを付けプログラムを終了する。
いかにもサンプルプログラムにありがちなプログラムとします。
- プロジェクトの作成
メニューから ファイル → 新規 → その他
新規ダイアログで JavaFX Projectを選択し、「次へ」をクリック
新規Javaプロジェクトのダイアログで プロジェクト名に「FxTest」と入力し、「次へ」をクリックビルドパス設定ダイアログでは 何も入力しないで 「次へ」をクリック。
下図のようにApplication type Desktop パッケージ名 com.nobotta 言語 FXML Root-Type javafx.scene.layout.BorderPane ファイル名 FxTest Controller Name FxTestController - FXML編集
パッケージエクスポーラのfxmlを右クリック
→ Open with SceneBuilderをクリック → SceneBuilderを起動します。
1) 左側のLibrary Containersから AnchorPaneを選択し 中央にドラッグし BorderPaneのCenterに配置します。
右側のLayoutのPrefWidth に 400 PrefHeight に 300 と入力します。2) 左側の Containers から BorderPane を選択し 上記AnchorPaneに配置
3) BorderPaneを右クリックし Fit To Parent をクリック
4) 左側の Controls から MenuBar を選択し 2) の BorderPane の Top に配置
5) 左側の Containers から GridPane を選択し 2) の BorderPane の Center に配置
6) 左側の Controls から 各Control 選択し 5)の GridPaneの各セルに配置
Cell位置 Control Text fx:id event(On Mouse Clicked) (0,0) Label 名前を入力してください (1,0) TextField txtName (0,1) Label ボタンをクリックしてください (1,1) Button OK btnOK_onClick (1,2) Label lblAnswer ここで Textは 右側の Properties を展開 fx:id および eventは Codeを展開して 入力します。
fx:idは コントローラクラス(FxTestController.java)の変数名、eventはメソッド名を示します。7) Menuから Edit Help を削除する
左側の Hierarchyを展開し AnchorPane > BorderPane > MenuBar と展開し
Menu Edit および Menu Help を右クリックし Delete をクリック
この手順で 4) で配置した MenuBarから Edit および Help を 削除します。8) Menu編集
左側の Hierarchyを展開し AnchorPane > BorderPane > MenuBar と展開
さらに Menu Fileを展開し
Menu File および MenuItem Closeに次の値を設定します。Text event(On Action) Menu File ファイル MenuItem Close 閉じる mnuClose_onClick メニューの File → Save をクリックすると FXMLが保存されます。
保存されたFXML(FxTest.fxml)
<?xml version="1.0" encoding="UTF-8"?> <?import java.lang.*?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.*?> <?import javafx.scene.layout.BorderPane?> <BorderPane xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.nobotta.FxTestController"> <center> <AnchorPane prefHeight="300.0" prefWidth="400.0" BorderPane.alignment="CENTER"> <children> <BorderPane prefHeight="300.0" prefWidth="400.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> <top> <MenuBar BorderPane.alignment="CENTER"> <menus> <Menu mnemonicParsing="false" text="ファイル"> <items> <MenuItem mnemonicParsing="false" onAction="#mnuClose_onClick" text="閉じる" /> </items> </Menu> </menus> </MenuBar> </top> <center> <GridPane BorderPane.alignment="CENTER"> <columnConstraints> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" /> </columnConstraints> <rowConstraints> <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> </rowConstraints> <children> <Label text="名前を入力してください" /> <TextField fx:id="txtName" GridPane.columnIndex="1" /> <Label text="ボタンをクリックしてください" GridPane.rowIndex="1" /> <Button mnemonicParsing="false" onMouseClicked="#btnOK_onClick" text="OK" GridPane.columnIndex="1" GridPane.rowIndex="1" /> <Label fx:id="lblAnswer" GridPane.columnIndex="1" GridPane.rowIndex="2" /> </children> </GridPane> </center> </BorderPane> </children></AnchorPane> </center> </BorderPane>
ハイライト表示した2行は、エラーになっています。これは イベント発生時の処理が、コントローラクラス(FxTestController.java)に実装されていないためです。
- Javaの実装
コントローラクラス(FxTestController.java)を開いて 以下の実装の追加を行います。
なお実装の追加を行った際 クラス未定義のエラーが発生します。importの追加など 適切なクイックフィックスを行います。1) FxTestController クラスに Initializable 属性を実装するpublic class FxTestController { }
を
public class FXTestController implements Initializable{ @Override public void initialize(URL location, ResourceBundle resources) { } }
と変更します。
2) 変数を宣言する
fxmlでfx:idを設定した変数を宣言します。@FXML private TextField txtName; @FXML private Label lblAnswer;
3) メソッドを実装する
最後に ボタン メニューのイベントハンドラーを実装します。@FXML private void btnOK_onClick(MouseEvent aEvent) { System.out.println("btnOK_onClick"); lblAnswer.setText(txtName.getText() + "さん こんにちは"); } @FXML private void mnuClose_onClick(ActionEvent event) { System.out.println("mnuClose_onClick"); Platform.exit(); }
これで コントローラクラス(FxTestController.java)ができました。
package com.nobotta; import java.net.URL; import java.util.ResourceBundle; import javafx.application.Platform; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.Label; import javafx.scene.control.TextField; import javafx.scene.input.MouseEvent; public class FxTestController implements Initializable{ @FXML private TextField txtName; @FXML private Label lblAnswer; @Override public void initialize(URL location, ResourceBundle resources) { } @FXML private void btnOK_onClick(MouseEvent aEvent) { System.out.println("btnOK_onClick"); lblAnswer.setText(txtName.getText() + "さん こんにちは"); } @FXML private void mnuClose_onClick(ActionEvent event) { System.out.println("mnuClose_onClick"); Platform.exit(); } }
- 実行してみます
名前を入力し、OKボタンをクリックすると 目的どおり 挨拶が表示されました。
また メニューで ファイル > 閉じる とすると プログラムが終了しました。
成功です!!
これで 初めて FXMLを使った JavaFXのプログラムができました。
のぼったの 素朴な感想
『Javaで本格的なGUIアプリを作る環境ができた。それが JavaFX』との振れ込みの割には、
SceneBuilderの操作性がイマイチ
JavaFX + SceneBuilder よりも SWT + WindowBuilder の方が完成度高そうに感じたのは 自分だけ??
もっとも SWTの場合は、OSによって プラグインを入れ替えなくてはならなかったり 折角Windowsで見た目きれいな画面を作っても 他のOSに持っていくと 妙に間が抜けた感じになったりしたけど、JavaFX では 他のOSに持って行ったとき 見た目はどうなんだろう??
雑誌の記事どおりに動かなかったり、WEB上の情報もちょっとすると古くなったり JavaFXって まだまだ 発展途上ってことかも
環境
OS Windows7 Professional ServicePack1
Eclipse 4.4