KotlinでもVBやVCのように簡単にデスクトップアプリを作ることが出来ます。
要点は以下のとおりです。
- IntelliJにTornadoFXプラグインをインストールする
- IntelliJからSceneBuilder(GUI作成ツール)を呼び出せるようにする
- Viewクラス(Formに相当)のrootプロパティにSceneBuilderで作成したFXMLファイルを関連付ける
- 使用したいウィジェット(Controlに相当)のfxidをプログラム中の変数と関連付ける
これから具体的な方法を説明します。
##必要なもの
IntelliJ (Commutity EditionでOK)
SceneBuilder
##準備
###SceneBuilder
http://gluonhq.com/products/scene-builder/ から
使用しているOS、JavaのバージョンにあったSceneBuilderをダウンロードしてインストールします。
※後で使うのでSceneBuilderファイルのインストール先を控えておきましょう。
###IntelliJ
次のプラグインをインストールします
TornadoFX (JavaFX、Kotlinは既に入っています)
設定
File → Settings → Languages & Frameworks → JavaFX
"Path to SceneBuilder" を設定します
※先ほど控えておいたSceneBuilderの保存先を設定します。
##プロジェクトの作成
今回はすべて初期値のままのプロジェクト名:untitledで作成します。
TornadoFX → tornadofx-gradle-projectを選択して
そのまま初期値でプロジェクトを作成します。
※2020年4月20日現在
このままではgradleのバージョンが古いのでビルドできません。
untitled/gradle/wrapper/gradle-wrapper.propertiesファイルを開いて
1行目のgradle-4.4-bin.zipのバージョンを変更します。
この原稿を書いている時点で最新版は6.3ですが、エラーが出るので5.6.4に変更しました。
MainVew.ktやMyApp.ktファイルを開いて左側にTornadoFXのアイコンが表示されていればOKです。
アイコンをマウスクリックして実行してみましょう。
うまく実行できない場合はRun → Edit Configurations...を開いてApp ClassやView Classが正しく設定されているか確認してください。
##FXMLファイルの作成
ここからが本番です。
src/mainフォルダの下にresourcesフォルダ、fxmlフォルダを作成し、その中にfxmlファイルを作ります。(マウスの右クリックで作成できます)
自動作成されるfxmlファイルにはfx:controllerの指定がありますが、これはいらないので行を削除するか、一旦全部削除してSceneBuilderで作りなおしてください。
SceneBuilderはプロジェクト画面でfxmlファイルをダブルクリックするか、右クリックしてコンテキストメニューの下の方にあるOpen In SceneBuilderで起動できます。
SceneBuilderの使い方はここでは割愛します。
次に進むためfxmlコードを全部削除して次のコードでfxmlファイルを作成してください。
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="243.0" prefWidth="382.0" xmlns="http://javafx.com/javafx/8.0.121" xmlns:fx="http://javafx.com/fxml/1">
<children>
<Button fx:id="sampleButton" layoutX="257.0" layoutY="128.0" mnemonicParsing="false" text="Button" />
<TextArea fx:id="sampleTextArea" layoutX="21.0" layoutY="19.0" prefHeight="200.0" prefWidth="200.0" />
</children>
</AnchorPane>
SceneBuilderで見ると次のようになります。
AnchorPaneにButtonとTextAreaを貼り付けただけのものですが、それぞれに"sampleButton","sampleTextArea"というfxidを設定しています。
##MainView.ktの書き換え
自動生成されるMainviewクラスは下のようになっています。
class MainView : View("Hello TornadoFX") {
override val root = hbox {
label(title) {
addClass(Styles.heading)
}
}
}
これを次のように書き換えます。
class MainView : View("Hello TornadoFX") {
override val root: AnchorPane by fxml("/fxml/main_view.fxml")
private val button: Button by fxid("sampleButton")
private val textArea: TextArea by fxid("sampleTextArea")
init {
button.action {
textArea.text = "Hello TornadoFX by FXML"
}
}
}
見てわかるとおり、Viewクラスのrootプロパティをby fxmlを使ってFXMLファイルに関連付けするだけです。
この例ではmain_view.fxmlファイルのトップレベルのコンテナAnchorPaneに合わせてrootプロパティもAnchorPaneで宣言しています。
あとは使用したいウィジェットをby fxidを使ってを使ってプライベート変数に関連付けします。
イベントハンドラはinit部で定義します。
上の例のbutton.actionメソッドの引数はop:() -> Unit型のラムダ式なので迷うことはありませんが、マウスクリック時の座標を取りたい時などは
**File → Settings → Editor → Appearance **
"Show parameter name hints" をチェックしておくと引数のヒントが表示されるので便利です。