ストロングゼロをほろよいで割った時のアルコール度数を計算できるアプリでJavaFXに入門する

この記事は [Mikatus Advent Calendar 2019](https://qiita.com/advent-calendar/2019/mikatus) 5日目の記事です。
#はじめに
皆さんはお酒が好きですか？
私はお酒が大好きですし、__多分お酒も私のことが好き__[^1]です。
[^1]: 片思いの可能性もある。
　　
最近では様々な缶チューハイが発売され、私も日々帰宅するなり晩酌をし、飲むだけ飲んだら眠りにつく日々を送っております。

しかし、昨今の缶チューハイは__某ストロング__を始めとした9%以上のものが増えてきました。
私もついついアルコール度数が高いものを買ってしまいがちですが、健康被害を考えると震え上がってしまい__お酒を飲まなければ眠れない毎日です__。

そんななか、職場の仲間から__「ほろよいで割ればOK」[^2]__と言われその発想に感動すると共に、お酒をお酒で割った時のアルコール度数とは・・・？となったので計算するデスクトップアプリをJavaFXで作ってみました。

[^2]: 何が大丈夫かは分からない。

#JavaFXとは
以下Wikipediaから引用
>JavaFX（ジャバエフエックス）とはJava仮想マシン上で動作するリッチインターネットアプリケーション (RIA) のGUIライブラリである。Java SE 7 Update 2以降に標準搭載されている。Swingとは異なり、FXMLと呼ばれるXMLとCSSを併用してデザインを記述する。

ざっくり言うとSwingの後継みたいな感じですかね。
SwingはUIも全部Javaで書かなければいけなくて結構地獄のような感じでしたが、JavaFXではFXMLというファイルにデザインを抽出したのでJavaでUIを書くことはないみたいです。

#環境構築&プロジェクト作成
こちらの記事を参考にさせていただきました。
[【超初心者向け】JavaFX超入門](https://qiita.com/tarosa0001/items/05ac653a091b7d1290f9)
プロジェクト構成、Mainクラスの記述は完全にコピペさせていただきました。

Scene Builderがかなり便利でパーツのドラッグ・アンド・ドロップでUIの構築は終わってしまいました。
<img width="1241" alt="スクリーンショット 2019-11-25 20.07.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/493116/3b219d2e-30de-52ce-59db-60d470dd83d9.png">
こんな感じです。

一つ注意点として上げるならば、JavaSE11からOracleJDKの無償版がなくなりOpenJDKを使用している人が大多数だと思いますが、__OpenJDKにはなんとJavaFXが含まれていません__。
今回は対応するのも面倒だったのでEclipseでプロジェクトを作成する際Java8を選択しました。

ちなみに対応方法もあるようです。
[OpenJFX + OpenJDK で JavaFX を動かす](https://skrb.hatenablog.com/entry/2018/05/29/210000)
[OpenJDK 11にJavaFXを導入する]
(https://blogs.osdn.jp/2018/11/12/merge-openjfx.html)

#FXMLをControllerに紐付ける
Scene BuilderでUIを作成して保存するとFXMLファイルで保存されます。
今回作ったFXMLファイルがこちら

```xml:名称未設定.fxml
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.Pane?>


<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <TextField layoutX="69.0" layoutY="98.0" />
      <TextField layoutX="300.0" layoutY="98.0" />
      <TextField layoutX="69.0" layoutY="201.0" />
      <TextField layoutX="300.0" layoutY="201.0" />
      <Button layoutX="503.0" layoutY="201.0" mnemonicParsing="false" text="計算する" />
      <Label layoutX="33.0" layoutY="103.0" text="1." />
      <Label layoutX="33.0" layoutY="206.0" text="2." />
      <Label layoutX="240.0" layoutY="103.0" text="ml" />
      <Label layoutX="240.0" layoutY="206.0" text="ml" />
      <Label layoutX="471.0" layoutY="103.0" text="\%" />
      <Label layoutX="471.0" layoutY="206.0" text="\%" />
      <Label layoutX="100.0" layoutY="285.0" prefHeight="48.0" prefWidth="401.0" />
   </children>
</Pane>
```

実際にやりたいこととしては、計算すると言うボタンが押下された際、4つのフォームに入力された値を取得して計算、と言う流れなのでボタン押下や4つのフォームに入力された値をJavaのControllerクラスで受け止められるようfxmlファイルを修正していきます。

そして出来上がったのがこちら

```xml:Main.fxml
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.Pane?>


<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controller.AlcoholController">
   <children>
      <TextField layoutX="69.0" layoutY="98.0" fx:id="amountFst" />
      <TextField layoutX="300.0" layoutY="98.0" fx:id="alcoholFst" />
      <TextField layoutX="69.0" layoutY="201.0" fx:id="amountSec" />
      <TextField layoutX="300.0" layoutY="201.0" fx:id="alcoholSec" />
      <Button layoutX="503.0" layoutY="201.0" mnemonicParsing="false" text="計算する" fx:id="button" onAction="#onClick" />
      <Label layoutX="33.0" layoutY="103.0" text="1." />
      <Label layoutX="33.0" layoutY="206.0" text="2." />
      <Label layoutX="240.0" layoutY="103.0" text="ml" />
      <Label layoutX="240.0" layoutY="206.0" text="ml" />
      <Label layoutX="471.0" layoutY="103.0" text="\%" />
      <Label layoutX="471.0" layoutY="206.0" text="\%" />
      <Label layoutX="100.0" layoutY="285.0" prefHeight="48.0" prefWidth="401.0" fx:id="result" />
   </children>
</Pane>
```

`fx:`で始まるタグが追加されているのがわかると思います。
まず一番大きなパネルの記述部分に`fx:controller`でFXMLファイルと紐付けるControllerを記述します。
TextFieldは`fx:id`をつけてあげます。これが後にControllerの変数と紐付きます。
Buttonには`onAction`で`onClick`を定義してあげます。
これでボタンが押下された際onClickというメソッドが動き出すはずです。

上記FXMLに合わせてControllerを作成します。

```java:AlcoholController.java
package controller;

import java.net.URL;
import java.util.ResourceBundle;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;

public class AlcoholController implements Initializable {

	@FXML
	private TextField amountFst;

	@FXML
	private TextField alcoholFst;

	@FXML
	private TextField amountSec;

	@FXML
	private TextField alcoholSec;

	@FXML
	private Button button;

	@FXML
	private Label result;

	@Override
	public void initialize(URL location, ResourceBundle resources) {

	}

	@FXML
	public void onClick(ActionEvent event) {

	}

}
```

こんな感じです。
`@FXML`をつけることで先程定義したFXMLファイルと紐づくみたいです。

あとはonClickに簡単な計算を書いて完成です。
<img width="600" alt="スクリーンショット 2019-11-25 20.27.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/493116/d654460c-3ed7-9151-9288-b8bb15cd8f9d.png">
これはアルコール９％のロング缶をほろよいで割った時のアルコール度数です。
__極めて健康的な数値__になっているのがわかります。

あとはEclipseから実行可能jarで書き出せば立派なアプリになりますね。

#最後に
Swingを書いた経験もありますが、やはりScene Builderがかなり便利だったのもあってSwingより断然楽でした。
Javaのコード自体もスッキリするので読みやすいですし、__数日間サボって日にちが空いても全然読めました__ね。

今回書いたソースはGithubにあげておくので良かったらご参考までに。
https://github.com/SomeyaHotaka/AlcoholCalc

このアプリで私は健康生活を送っていこうと思います。
それではまた。