VSCode + Gradle で構築したプロジェクトで JavaFX を実装する
エディタに VSCode、ビルドツールに Gradle を使用した Java プロジェクトで、JavaFX を使ってみる。
JavaFX とは、AWT や Swing の後発ライブラリで、Java 言語でクロスプラットフォームな GUI アプリを作るためのライブラリだ。
実装するにあたって、いくつか手を入れないとうまく動かなかったので、その点を紹介する。
目次
- 前提条件
.classpath
を編集して JavaFX を参照できるようにするbuild.gradle
を編集して JavaFX 込みのビルドができるようにする- JavaFX を実装してみる
- アプリを起動してみる
前提条件
前提条件は以下のとおりとする。
- JDK は JavaFX が同梱されている JDK8 を使用する
- 現在の JDK には同梱されていないので、最新版の JDK で構成する場合は、OpenJDK と OpenJFX を入れる必要があるらしい (試していない)
$ gradle init --type java-application
で雛形を作成しておく- VSCode に拡張機能「Java Extension Pack」をインストールしておく
VSCode に拡張機能を入れたあと Gradle プロジェクトを開くと、
.project
.classpath
bin/
などのファイルが自動的に生成される。これらによって VSCode 上の自動補完などが効くようになるようだ。
.classpath
を編集して JavaFX を参照できるようにする
現状、VSCode 上でコードを入力しても、JavaFX 関連のクラス名だとうまく自動補完が効かない。そこで、.classpath
ファイルを開いて次のように編集すると、自動補完などが効くようになる。
<!-- ↓元はこのような行がある -->
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/" />
<!-- ↓次のように編集する -->
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/">
<accessrules>
<accessrule kind="accessible" pattern="javafx/**" />
<accessrule kind="accessible" pattern="com/sun/javafx/**" />
</accessrules>
</classpathentry>
このように accessrules
要素でパッケージを参照できるようにしておく。これは外部 JAR ライブラリを導入する場合も必要になることがあるので、覚えておくと良いかと。
<!-- 例として OpenCV の JAR ファイルを読み込む場合 -->
<classpathentry kind="lib" exported="true" path="lib/opencv.jar">
<accessrules>
<accessible kind="accessible" pattern="**" />
</accessrules>
</classpathentry>
コレを自動でなんとかしてくれる方法がないか調べたが、よく分からず。良い管理方法があったら教えてほしい。
build.gradle
を編集して JavaFX 込みのビルドができるようにする
.classpath
の記述は VSCode 上の自動補完やコンパイルにのみ影響するらしい。gradle build
コマンドなどを使う際の依存関係は、build.gradle
ファイルを編集しないといけない。
JavaFX を使う上で必要な変更を以下に記す。
plugins {
// 既存の 'java' と 'application' はそのままに以下を追加
// classpath を出力させて自動補完を効かせる
id 'eclipse'
}
dependencies {
// 既存の依存関係はそのままに以下を追加
// JavaFX を追加する
compile files("${System.properties['java.home']}/lib/ext/jfxrt.jar")
}
// Java ファイルと同じ階層に FXML ファイルを置けるようにする
sourceSets {
main {
java {
srcDir 'src'
}
resources {
srcDir 'src/main/java'
}
java.outputDir = file('bin')
output.resourcesDir = file('bin')
}
}
ユニットテストが鬱陶しい場合は以下を消してしまえば、./test/
配下のファイルによる影響をなくせる。
dependencies {
// Use JUnit test framework
testImplementation 'junit:junit:4.12'
}
JavaFX を実装してみる
試しに JavaFX を用いたウィンドウを開いてみる。とっても簡素なモノだ。
src/main/java/my_app/App.java
- エントリポイント
package my_app;
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
public final class App extends Application {
public static void main(final String ...args) {
launch(args);
}
@Override
public void start(final Stage primaryStage) throws IOException {
final FXMLLoader loader = new FXMLLoader(getClass().getResource("./root.fxml"));
final Pane root = loader.load();
final Scene scene = new Scene(root, 600, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
}
FXMLLoader
を使い、root.fxml
というファイルを読み込んでいる。
src/main/java/my_app/root.fxml
- コンポーネントの UI (View) を定義する XML 風のファイル
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.HBox?>
<HBox xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="my_app.RootController">
<Label text="TEST" />
</HBox>
先程 build.gradle
で sourceSets
ブロックを記述したので、.java
ファイルと同じ階層に .fxml
ファイルが置けるようになった。
fx:controller
属性で対応するクラスを指定している。
src/main/java/my_app/RootController.java
root.fxml
に紐付くコントローラクラス
package my_app;
public final class RootController { }
今回は特に処理を入れていないので、コントローラクラスには実装なし。
- Initializable を実装すれば、
FXMLLoader
をload()
したタイミングで初期処理が実行できる - 画面上の要素に
fx:id
属性を付与すれば、コントローラ側でその要素を特定して参照できる<Label fx:id="myLabel" />
@FXML private Label myLabel;
とアノテーション付きでフィールドを宣言するthis.myLabel.setText("HOGE FUGA");
というように要素を操作できる
onAction
属性を使えば、ボタンからコントローラのメソッドを呼び出したりできる<Button onAction="#onExec" text="実行する" />
@FXML public onExec() {}
とアノテーション付きでメソッドを宣言する
どんなレイアウトがあって、どんなコントロール部品があるのか、どうやってプロパティを設定したらいいか、とかいうことは、チマチマ検索していくしかない…。「こういうことをやりたいんだけどどうやるんだろう?」という逆引きは StackOverflow が参考になると思う。
アプリを起動してみる
とりあえずココまで実装すると、
$ ./gradlew run
で Java アプリが起動する。実行割合が 75% 程度で止まったまま、GUI ウィンドウが開くことが確認できると思う。ウィンドウを閉じたり、Ctrl + C でターミナルを終了したりすれば良い。
今日はココまで。