OpenJDK + OpenJFXでJavaアプリ開発環境構築

# はじめに
PCを新調したので改めてJavaの開発環境を構築したので，メモも兼ねて記事作成．

OpenJDK + OpenJFXのインストールとEclipse上の設定までの手順．

JavaFXを使うこともあって，あらかじめ同梱されてる（らしい）Liberica JDKというディストリビューションをつかおうと思いましたが，いろいろ詰まったので結局それぞれOpen JDKとOpenJFXでやることにしました．

## Open JDKとOpenJFXのインストール

### Open JDK

Oracleの[公式ページ](https://jdk.java.net/)より「JDK」からプラットフォームに合ったものをDLしましょう．
![スクリーンショット 2023-12-04 103442.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1857903/5f03880f-caca-d6f7-ec6c-9eae5b6ecc63.png)
![スクリーンショット 2023-12-04 104918.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1857903/1c79d704-d82e-f448-d2bb-242289622b9a.png)

適当な場所に解凍して環境変数を通します
- 「（略）/jdk-xx.x.x/bin」を環境変数"PATH"に追加
- 「（略）/jdx-xx.x.x/」を環境変数"JAVA_HOME"に追加 [^JAVAHOME] （なければ新規作成）

最後にターミナルでコマンドを売ってパスが通っているか確認しましょう．

```shell-session
>java --version
```

![スクリーンショット 2023-12-04 104115.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1857903/8421152d-124c-bda2-d82a-c3dce68c4580.png)
インストールしたバージョンが表示されればOK.

### Open JFX

Open JDKと同じく，Oracleの公式ページから配布ページに飛べます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1857903/c4a86448-b7c9-ed6c-657c-15d45fc51de6.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1857903/040b03a0-c80a-c0d2-f5c6-782aa127d742.png)

SDKとJMODsという２つの項目がありますが，開発に必要なSDKをダウンロードしましょう．
JMODsは配布用のスタンドアロンJarを作るときに必要なはず．

ダウロードした圧縮ファイルを解凍したら，適当なところに配置しておきましょう．

### Scene Builderのインストール

JavaFXはSwingやAWTと異なり，ソースコードにコンポーネントをハードコードするのではなく，FXMLというファイルにコンポーネントやその入れ子構造を記述してGUIを構成します．
FXMLをハンドライトするのは非効率的なので，直感的にGUIを作成できるツールがあります．
それが「Scene Builder」です．
![2023-12-04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1857903/46b2d2a5-083e-5d89-d0bf-e38b0d3b4229.png)
Gluonの[公式ページ](https://gluonhq.com/products/scene-builder/)よりインストーラをダウンロードできます
インストール先はのちの設定で必要になるので控えておいてください．

## Eclipseのインストールと設定

### Eclipseのインストール

Pleiadesの[公式ページ](https://willbrains.jp/)よりPleiades All in One Eclipseのお好みのエディション，バージョンをダウンロードして適当なところに解凍しましょう[^PLEIADES]

JDKを自前でインストールしているので，一番同梱物の少ないPlatformエディションでも問題ないと思います．

### JavaFX向け拡張機能のインストール

Eclipseを起動し，ウィンドウ上端のメニューより[ヘルプ]→[Eclipse マーケットプレース]からマーケットプレースを起動．
検索ボックスにJavaFXと入力してEnter
トップに出てくる拡張機能「e(fx)clipse」をインストール
![スクリーンショット 2023-12-04 110748.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1857903/d0879841-88c4-5986-ff35-b5cfc5f6193c.png)

インストール時に規約に同意するか聞かれるのでOKでそのまま進みましょう．

### 拡張機能の設定

拡張機能にJavaFX開発で必要な「JavaFX SDK」と「Scene Builder」のパスを教えてあげる必要があります．
Eclipseのウィンドウ上端のメニューバーより，「ウィンドウ」->「設定」から設定ウィンドウを開き，左のツリーから「JavaFX」をクリックします．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1857903/2f5bef52-5c56-d7ec-68be-47a8d9abccbe.png)
ここにScene Builderの本体とJavaFXのディレクトリの"lib"ディレクトリを指定します．

## JavaFXプロジェクトの作成

以上で環境設定は終わりです．
最後に簡単なJavaFXアプリケーションを作って終わりにしましょう．

### 新規プロジェクトの作成

新規Javaプロジェクトを作成しましょう
Eclipseのメニューより「ファイル」->「新規」->「プロジェクト」を選択します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1857903/2e9d68bb-536e-5579-5f00-c7b2e2ef3983.png)
表示されたウィンドウのツリーから「JavaFX」->「JavaFXプロジェクト」を選択して，「次へ」をクリックしてください．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1857903/8066c896-bb8e-a2aa-4152-6528743b41d6.png)

プロジェクトの設定は，プロジェクト名を「HelloJavaFX」として「次へ」を押してください．
![スクリーンショット 2023-12-04 130515.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1857903/f6ca6256-9cd7-978c-6d8c-1f064c104f4e.png)
Javaビルド設定が表示されるので，「ライブラリー」タブを開いて「外部JARの追加」をクリックしてください．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1857903/ff8a6760-255d-0636-0e59-7222fd7f6056.png)
ファイルダイアログが開くので，JavaFX SDKのディレクトリ内の"lib"ディレクトリ直下のJarファイルをすべて選択してください．

モジュールパスに追加されたことを確認したら「次へ」を押してください．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1857903/c26f0a9b-d083-a1ce-4083-a31fc303ff62.png)

最後に，JavaFX固有の設定が表示されます．
ここで，「宣言的UI」内部の「言語」を「FXML」に変更してください．
他のオプションは気にしなくていいです．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1857903/ab3676ff-242d-cc9f-31af-ce6fa920ef32.png)
「完了」ボタンを押せばプロジェクトの作成は終わりです．
### ファイル構成
以上の手続きで出来上がったJavaFXプロジェクトがこちらです．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1857903/07eea977-0307-be7c-bc81-89906eb3bb9c.png)
- Main.java
    - アプリケーションのエントリーポイント．FXMLとCSSの読み込み等の初期化処理を担当．
    - 基本はいじらない
- SampleController.java
    - イベントハンドラを記述するファイル
    - 名前の通りMVCのCにあたる処理を書くところ
    - イベント処理の実装をここに書くといずれ肥大化するので，ロジックは別ファイルに書いてハンドラから別ファイルのメソッドに投げるのが吉（というかMVCのModelとControllerの関係ってそういうことですよね）
- Sample.fxml
    - GUIの構成を記述するファイル
    - 基本的にはScene Builderで編集
    - コンポーネントによってはScene Builderで設定できないプロパティがあるので（確かあったはず），エディタで開いて編集することもある

後のファイルは気にしなくていいです．

### GUI作成

まずはガワから作りましょう．
パッケージエクスプローラよりSample.fxmlを右クリックして「Scene Builderで開く」をクリックしてください．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1857903/0505af7d-e98f-8d9a-fdaa-b2f735d9feb4.png)
そうするとScene Builderが立ち上がります．
今回は「ボタンを押した回数をラベルに表示する」というアプリケーションを作りたいので，ボタントラベルを配置しましょう．
ウィンドウ左のアコーディオンメニューの「Control」内に「Button」と「Label」があります．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1857903/e658e0db-89ff-389f-ee59-998717880a99.png)

ドラッグ＆ドロップでウィンドウに配置しましょう
ウィンドウ中央にD&Dでも配置できますが，ウィンドウ左側のメニューの下部，「階層」にD&Dすることでコンポーネントの階層構造を指定して配置できます．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1857903/8342ab78-50c9-ebdc-db9a-de0832b1a222.png)
ウィンドウの中央にプレビューが表示されます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1857903/26b4dee7-8643-1e28-2e9a-bf23dab03b69.png)

コンポーネントをクリックして選択すると，ウィンドウ右側のサイドバーにプロパティが表示されます．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1857903/147e75ad-2363-c6fd-ccf8-533ceba09694.png)
設定項目は３つに分類できます
- Properties
    - コンポーネントの内部情報を設定できます
    - 主にテキストの設定やCSSセレクタの設定ができます
- Layout
    - 他コンポーネントとの位置関係を設定ができます
    - 主にマージンやパディングの設定ができます
- Code
    - Controllerと強調する設定ができます
    - Controller側から参照するためのIDの設定やイベント発生時のハンドラを設定できます

とりあえずButtonのラベルを「Click」にLabelのテキストを" "(空白)に設定しました．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1857903/a44a3fe5-e32b-25c1-a2b2-2239897ce1b1.png)

さて，Controllerと連携するためにはCodeメニューからハンドラとIDを設定する必要がありますが，先にSampleController.javaの準備をしましょう．

### コントローラの準備

Eclipseに戻ってSampleController.javaを開きましょう

```java:SampleController.java
package application;

public class SampleController {
	
}
```
ここにコンポーネントの参照と，イベントハンドラを追加します．
```diff_java:SampleController.java
package application;

+import javafx.fxml.FXML;
+import javafx.scene.control.Label;
+import javafx.event.ActionEvent;

public class SampleController {
+	@FXML
+	private Label clickCount;

+	@FXML
+	protected void handleButtonClicked(ActionEvent e) {
+	}
}
```
`@FXML`というアノテーションは，FXMLと連携するために必要なもので，これをつけておくとGUIとコントローラでつなげてくれます．
今一度Scene Builderに戻ってGUI側の設定も済ませましょう．
### Scene Builderからの設定
Buttonにはイベントハンドラを，LabelにはIDを設定しましょう．
#### イベントハンドラの設定
配置したButtonをクリックして選択し，右のメニューから「Code」->「On Action」にハンドラを設定します．
編集したSampleController.javaを保存していれば，サジェストが出るはずです．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1857903/201861e1-bceb-07c5-cca4-4a87c0875372.png)

これを選択すればハンドラの設定は終わりです．
#### IDの設定
次にLabelを選択して同じように右のメニューの「Code」->「fx:id」を見てみます．
Buttonのハンドラの時と同じようにサジェストが出るのでそれを選択します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1857903/4fcbf192-6b2e-6865-dcfe-878509691ddc.png)


以上でSceneBuilderを使った設定は終わりです．
保存して閉じましょう．

次はイベントハンドラの中身を記述していきます．
### イベントハンドラ実装
カウンタは別クラスにシングルトンで実装します．
一応，コントローラクラスにも初期化処理を書いて状態を持たせることはできるのですが，クラスの担当が増えるのであまりお勧めしません．
デフォルトで`application`というパッケージができているので，この下に`logic`というパッケージを作ってそこに`Counter.class`を作成します．
```java:Counter.java
package application.logic;

public class Counter {
	private static Counter instance = new Counter();
	private int count;

	private Counter() {
		count = 0;
	}

	public void addCount() {
		this.count++;
	}

	public int getCount() {
		return this.count;
	}

	public static Counter getInstance() {
		return Counter.instance;
	}
}
```
`SampleController.java`に戻ってイベント処理を書き上げましょう
```diff_java:SampleController.java
package application;

+import application.logic.Counter;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
public class SampleController {
	@FXML
	private Label clickCount;

	@FXML
	protected void handleButtonClicked(ActionEvent e) {
+		Counter counter = Counter.getInstance();
+		counter.addCount();
+		int count = counter.getCount();
+		clickCount.setText(Integer.toString(count));
	}
}
```
これでイベントハンドリングも終わりです．
では実行してみましょう．
### 実行結果
![click_count.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1857903/6b2902ed-9908-f094-b86a-df57d1bfd069.gif)

これでおしまいです！
ビューとコントロールが初めから分離されてるので，かなりきれいにデスクトップアプリケーションが作れますね
## 終わりに
JavaFXの環境構築から適当なデスクトップアプリケーションの作成までを解説しました．
ここまでできれば簡単なアプリケーションであればすぐに実装できるのではないかと思います．

最近はずっとPython+TkinterでGUI作ってたから久しぶりに触ったJavaFXの便利さに感動してます．

今回のサンプルプログラムは[こちら](https://github.com/maruKuni/HelloJavaFX.git)です．
Eclipseにインポートした後設定を直す必要があるかもしれませんが…
[^JAVAHOME]:不要かも
[^PLEIADES]:Windowsではパス長に制限があるので，できる限りC:直下に近いところに解凍しましょう