19
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

JavaAdvent Calendar 2019

Day 5

IntelliJ IDEAとGradleでのJavaFXアプリケーション開発 〜環境構築からサンプルコードまで〜

Last updated at Posted at 2019-12-04

#0.はじめに
いま、筆者は絶賛GUIツールを使ったソフトウェアを作る必要に迫られています。
ずっと放置していて最近着手したのですが、思いの外環境構築に手間取ったので備忘録を兼ねてここに書いておきます。

#1.JavaFXって何ぞ?
「JavaでGUIと言ったらAWT!Swing!」と思っている方はいませんか?
実は最近、JavaFXというフレームワークが出てきてかなりGUIツール開発のハードルが下がったと聞いています(聞いているだけ)。

筆者はたまたま、「あー、GUIかー、どうやって作るんだろうなー」とネットを彷徨っていたら見つけました。
今日はそんな便利そうなJavaFXの入り口を少しだけご紹介します。

#2.筆者の環境

  • MacBook Pro (Early 2015)
  • macOS Mojave (10.14.6)
  • IntelliJ IDEA Community Edition (2018.3.1)
  • OpenJDK (13.0.1)

#3.環境構築
##3.1.OpenJDKのインストール
###3.1.1.ダウンロード
OpenJDKのサイトから自分が使いたいバージョンのJDKをダウンロードします。
ただし、JavaFX側がJDK11以上を必要とするので注意。

■上記のサイト
191121-0001.png
この画像の真ん中あたり、macOS/x64の右にあるtar.gzのリンクからダウンロードします。
私は13.0.1を使いました。

###3.1.2.インストール
ダウンロードしたtar.gzファイルを展開し、以下のディレクトリに移動します。
/Library/Java/JavaVirtualMachines

/
└── Library
    └── Java
        └── JavaVirtualMachines
            └── jdk-13.0.1.jdk
                └── Contents
                    └── ...

確認として以下のコマンドを実行します。

$ /usr/libexec/java_home -V
Matching Java Virtual Machines (2):
    13.0.1, x86_64:	"OpenJDK 13.0.1"	/Library/Java/JavaVirtualMachines/jdk-13.0.1.jdk/Contents/Home
    11.0.2, x86_64:	"OpenJDK 11.0.2"	/Library/Java/JavaVirtualMachines/jdk-11.0.2.jdk/Contents/Home

/Library/Java/JavaVirtualMachines/jdk-13.0.1.jdk/Contents/Home

実行結果が全く同じでなくても構いません。
今インストールしたバージョンが認識されているか確認してください。

##3.2.プロジェクトのセットアップ
###3.2.1.プロジェクトの作成
IntelliJ IDEAを立ち上げ、Create New Projectから新しいプロジェクトを作ります。
今回はGradleを使ってJavaFXを利用するので、もちろんGradleのプロジェクトを作りましょう。

■プロジェクト作成画面
191121-0002.png
Project SDKは13になるように設定をしておいてください。

次の画面でGroupId, ArtifactIdを指定します。

さらに次の画面はプロジェクトの設定をする場所ですが、私はここは基本的にいじりません。
Gradle JVMが13になっていることを確認するだけでいいと思います。

その次の画面で使用するフォルダを指定したらプロジェクトが作成されます。
諸々の処理が終わるまで少し待ちましょう。

###3.2.2.build.gradleの設定
※以下、私のプロジェクトでのフォルダ構成で書きます。
フォルダ構成によって記述が変わる箇所は下の方にまとめて書きます。

build.gradleに以下の部分を追記します。
書いていないところは何も編集していません。

build.gradle
plugins {
    id 'application'
    id 'org.openjfx.javafxplugin' version '0.0.8'
}

dependencies {
    //このruntimeOnly群はクロスプラットフォーム対応のjarを作るためのものです。
    //不必要なものは消すとjarファイルのサイズを小さくできます。
    runtimeOnly "org.openjfx:javafx-base:$javafx.version:win"
    runtimeOnly "org.openjfx:javafx-base:$javafx.version:linux"
    runtimeOnly "org.openjfx:javafx-base:$javafx.version:mac"
    runtimeOnly "org.openjfx:javafx-controls:$javafx.version:win"
    runtimeOnly "org.openjfx:javafx-controls:$javafx.version:linux"
    runtimeOnly "org.openjfx:javafx-controls:$javafx.version:mac"
    runtimeOnly "org.openjfx:javafx-fxml:$javafx.version:win"
    runtimeOnly "org.openjfx:javafx-fxml:$javafx.version:linux"
    runtimeOnly "org.openjfx:javafx-fxml:$javafx.version:mac"
    runtimeOnly "org.openjfx:javafx-graphics:$javafx.version:win"
    runtimeOnly "org.openjfx:javafx-graphics:$javafx.version:linux"
    runtimeOnly "org.openjfx:javafx-graphics:$javafx.version:mac"
}

javafx {
    version = "13"
    modules = [ 'javafx.controls', 'javafx.fxml' ]
}

mainClassName = 'maru.test.Launcher'
jar {
    manifest {
        attributes 'Main-Class': 'maru.test.Launcher'
    }
    from {
        configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
    }
}

■今こんな感じ(下の方ちょっと切れてます)
191122-0003.png

#4.サンプルのプロジェクトを動かす
##4.1.サンプルコードの実装
サンプルコードはOpenJFXの公式さんからお借りしました。

src/main/java/maru/test/Launcher.java
package maru.test;

import javafx.application.Application;

public class Launcher {
    public static void main(String... args){
        Application.launch(MainApp.class);
    }
}
src/main/java/maru/test/MainApp.java
package maru.test;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;


public class MainApp extends Application {
    
    @Override
    public void start(Stage stage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("scene.fxml"));
        
        Scene scene = new Scene(root);
        scene.getStylesheets().add(getClass().getResource("styles.css").toExternalForm());
        
        stage.setTitle("JavaFX and Gradle");
        stage.setScene(scene);
        stage.show();
    }
}
src/main/java/maru/test/FXMLController.java
package maru.test;

import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;

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

public class FXMLController implements Initializable {
    
    @FXML
    private Label label;
    
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        String javaVersion = System.getProperty("java.version");
        String javafxVersion = System.getProperty("javafx.version");
        label.setText("Hello, JavaFX " + javafxVersion + "\nRunning on Java " + javaVersion + ".");
    }
}
src/main/resources/maru/test/scene.fxml
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.StackPane?>


<StackPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="maru.test.FXMLController">
    <children>
        <Label fx:id="label" text="Label" />
    </children>
</StackPane>
src/main/resources/maru/test/styles.css
.label {
    -fx-text-fill: blue;
}

■こんな感じ
191122-0004.png

##4.2.コンパイル、実行
右上の方にあるGradleをクリック、Tasks>build>buildを実行します。
それが終わったら少し上のTasks>application>runを実行します。

■これです
191122-0005.png
こんな感じのが出てきたら成功です!

■「こんな感じの」
191121-0006.png
build/libs/にjarファイルができていると思います。
このjarファイルはfatjar(ライブラリとかも含んでいるjarファイル)なので、誰のPCでも動くはずです。
ごめんなさい多分嘘つきました。fatjarが欲しかったらshadowを入れましょう。

##4.3.フォルダ構成によって記述が変わる場所
<>で囲まれている場所をよしなに変えてください。
フォルダ構成に左右される箇所だけ抜き出しています。

ファイル名
build.gradle 2箇所
Launcher.java 1箇所
MainApp.java 2箇所
scene.fxml 1箇所
build.gradle
mainClassName = '<Applicationクラスを継承していないランチャー用のクラス>'
jar {
    manifest {
        attributes 'Main-Class': '<上のmainClassNameと同じ>'
    }
}
Launcher.java
public static void main(String... args){
    Application.launch(<Applicationクラスを継承しているクラス>.class);
}
MainApp.java
@Override
public void start(Stage stage) throws Exception {
    Parent root = FXMLLoader.load(getClass().getResource("<fxmlファイル>"));
    scene.getStylesheets().add(getClass().getResource("<cssファイル>").toExternalForm());
}
scene.fxml
<StackPane (中略) fx:controller="<Controllerクラス>">

おそらく以上です。見落としがあったらごめんなさい。。。

#5.最後に
どうでしたか?思ったより簡単だったのではないでしょうか?

ちなみに、画面の構築にはSceneBuilderが便利です。
IntelliJ IDEAの設定をすればこんなこともできちゃいます。

■こんなこと
191122-0001.png
これでGUIアプリケーション開発のハードルがグッと下がったのではないでしょうか。
皆さんもよいGUIアプリケーションライフをお楽しみください!

#6.参考文献

19
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?