LoginSignup
4
2

More than 1 year has passed since last update.

[備忘録]JavaFX/Scene Builderで画面遷移するシステムを作ってみる

Last updated at Posted at 2022-05-23

1. はじめに

今回は、JavaFXで学んだことをアウトプット、備忘録としてここに記します。

使用環境

windows10

Java - 17.0.2
Eclipse - 2021-12 (4.22.0)
JavaFX - 17.0.3(2022年4月)
Scene Builder - JavaFX SceneBuilder1.1

2. JavaFXの導入

◆JavaFXの安定バージョンをダウンロードします。

2022/5/23時点では、17.0.3がサポート対象でした。

JavaFX公式 - ダウンロードページ

ダウンロードしたものを展開する場所は分かりやすい作業フォルダに置く

◆Windowsのシステム環境変数とEclipseにパスを通しましょう

Windowsシステム環境変数に追加
変数名は適当に、JavaFX_path

ドライブ名:\保存先\javafx-sdk-18.0.1\lib

のように/libファイルの中身を見れるようにシステムに教えてあげましょう。

システムにパスを通さないとEclipseからパスを通せません。

※EcelipseはJavaFXプロジェクトを作ってから外部jarファイルとして追加します。

3. Scene Builderをインストール

Oracle - Scene Builder ダウンロードページ

上記のページから一番下のあたりにある
[JavaFX SceneBuilder1.1ダウンロード]
から各自OSのバージョンをダウンロードしてください

4. JavaFX Projectを作成

4.1. JavaFXを作る前に

JavaFXは画面を見た目を構築する  .fxmlファイル
とその画面をコントロールする  .javaのコントローラーファイル

の2つのセットで構築されています。

Scene Builderはその.fxmlをGUI表示して直感的に画面構成を変えることでScene Builderが.fxmlを書き換えてくれるツールです。

以下のようにEclipseからMain.javaを実行すると、新しいウインドウでアプリが起動する状態を目指します。

javafx画面.PNG

では、実際に作っていきます。

4.2. Eclipseにて、JavaFXプロジェクトを作る

Eclipseのプロジェクト作成から、JavaFX/JavaFXプロジェクトを選択します。

  1. Eclipse画面上部のリボンにある
    ウインドウ > 設定 > Java > ビルド・パス > ユーザー・ライブラリー > 新規

  2. 新規作成ボタンで JavaFX と入力し、フォルダを作成

  3. 外部jarファイルの追加

  4. システム環境変数で設定したパスと同じ場所 /lib の中にある すべての.jarファイルを選択して、適用ボタンを押す。

以下のような状態になっていればok

eclipseにjarファイル追加.PNG

  1. ロジェクトの作成 > その他 > JavaFX > JavaFXプロジェクト

  2. プロジェクト名を決めて、JREがJavaSE-17になっていれば、次へ

  3. ライブラリータブ > クラスパスを選択した状態で > 外部jarファイルの追加(先ほどEclipseでパスを通した手順と同じことをします)、次へ

  4. 宣言的UI > 言語を[FXML]にする

ルートタイプ: 変更しない
ファイル名: Main
コントローラー名: MainController

完了ボタンでプロジェクトが作成される

参考ページ
【超初心者向け】JavaFX超入門

5. 画面を作ろう

src/application/内の○○Controller.javaと○○.fxmlをパッケージ化します。

src/application/main/MainScreen.fxml
src/application/main/MainController.java

Screen.fxmlはそのままの階層においてください
Main.javaは実行ファイルなのでそのままの階層においてください

5.1. Main.java

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

public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        try {
            //FXMLからのシーングラフの読み込み
            FXMLLoader loader = new FXMLLoader(getClass().getResource("main/MainScreen.fxml"));
            Parent root = loader.load();

            //シーングラフのルートノードを設定したシーンの作成
            Scene scene = new Scene(root, 1000, 600);
            //ステージへのシーンの設定
            primaryStage.setScene(scene);
            primaryStage.setTitle("[ウィンドウの名称を変更できます]");
            primaryStage.show();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}

5.2. Scene Builderでログイン画面の見た目を作る

  • MainScreen.fxmlを右クリックしてScene Builderで開く

loginform.PNG

このような画面を作ります。

  • Containers / vBoxを黒い画面上に置くと、真っ白な画面ができると思います、

赤①
Containers / Text

  • Properties: 好きな文章をいれてください
  • Code: fx:idはつけなくてもいいです

橙②
Containers / TextField

  • Properties: Prompt Text - にuser_nameを入れると、Text Fieldの背後にうっすらと文字が表示されます。
  • Code - [user_name] というidを付けます。

黄③
Containers / Button

  • Properties: Text - [System exit]を入力
  • Code: fx:id - に[closeButton]
  • Code: On Action - に[OnClickedCloseButton]を入力

Containers / Button

  • Properties - Text [login]を入力
  • Code: fx:id - [nextButton]
  • Code: On Action - [OnClickedNextButton]

これで更新を書けると注意マークが上部にでます

⇒ Controllerでこれらの動作について定義すればこの警告は消えます。

5.3. MainScreen.fxml

MainScreen.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?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>

<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.main.MainController">
   <children>
      <Button fx:id="nextButton" layoutX="411.0" layoutY="323.0" mnemonicParsing="false" onAction="#OnclickedNextButton" prefHeight="33.0" prefWidth="91.0" text="login" />
      <Button fx:id="closeButton" layoutX="109.0" layoutY="323.0" mnemonicParsing="false" onAction="#OnclickedCloseButton" prefHeight="33.0" prefWidth="91.0" text="system exit" />
      <Label alignment="CENTER" layoutX="200.0" layoutY="75.0" prefHeight="33.0" prefWidth="200.0" text="Question-Maker">
         <font>
            <Font size="20.0" />
         </font>
      </Label>
      <TextField fx:id="user_name" layoutX="226.0" layoutY="168.0" promptText="user name" />
      <TextField fx:id="password" layoutX="226.0" layoutY="213.0" promptText="password" />
      <Text layoutX="142.0" layoutY="185.0" strokeType="OUTSIDE" strokeWidth="0.0" text="User Name: " />
      <Text layoutX="146.0" layoutY="230.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Password: " />
      <TextField fx:id="again_pass" layoutX="226.0" layoutY="258.0" promptText="again_pass" />
      <Text layoutX="136.0" layoutY="275.0" strokeType="OUTSIDE" strokeWidth="0.0" text="again_pass: " />
   </children>
</Pane>

5.4. コントローラーに処理を書いていく

MainController.javaを編集します。

その前に、Scene Builderにて上部のタブから、

表示 > サンプル・コントローラー・スケルトンの表示を押すと

MainController.javaに書くべき各コンテナの定義情報が記載されますので丸ごとコピーしてこの状態から書き始めます。

Controllerで、fxmlの各要素を参照しているわけです.

以下のようにTextFieldにある文字列を受け取って、データベースの情報と照合する処理を
書けば、ログイン機能のような画面遷移ができます。

5.5. MainController.java

MainController.java
package application.main;

import java.net.URL;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.ResourceBundle;

import application.Screen;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;

public class MainController {

    @FXML
    private ResourceBundle resources;

    @FXML
    private URL location;

    @FXML
    private Button nextButton;

    @FXML
    private Button closeButton;
    
    @FXML
    private TextField user_name;
    
    @FXML
    private TextField password;
    
    @FXML
    private TextField again_pass;

	@FXML
    void OnclickedCloseButton(ActionEvent event) {
        closeButton.getScene().getWindow().hide();          //システム終了
    }

    @FXML
    void OnclickedNextButton(ActionEvent event) throws SQLException, ClassNotFoundException {
    	// データベースから情報を持ってくる処理
    	
    	if (回目のパスワード入力と2回目のパスワード入力の文字列が同じか) { 
    		if (データベースの情報と合っているか) {
    			// 画面遷移処理
    			nextButton.getScene().getWindow().hide();
                Screen screen = new Screen();                 
                // 引数 (次の画面の.fxml, "画面名");
                screen.transitionScreen("home/SubScreen.fxml", "HOME");
    		}
    	} else {
    		System.out.println("user login missed");
    	}
        
    }

    @FXML
    void initialize() {
        assert nextButton != null : "fx:id=\"nextButton\" was not injected: check your FXML file 'screen.fxml'.";
        assert closeButton != null : "fx:id=\"closeButton\" was not injected: check your FXML file 'screen.fxml'.";

    }
   
}

5.5. 遷移先の画面

遷移先の画面も作っておきます。

5.6. SubScreen.fxml

SubScreen.fxml
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.text.Font?>

<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" style="-fx-border-radius: 20;" xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.home.SubController">
   <children>
      <Button fx:id="backButton" layoutX="458.0" layoutY="21.0" mnemonicParsing="false" onAction="#OnclickedBackButton" prefHeight="33.0" prefWidth="110.0" text="Back to Login">
         <padding>
            <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
         </padding></Button>
      <Label alignment="CENTER" layoutX="39.0" layoutY="6.0" prefHeight="25.0" prefWidth="200.0" text="Question-Maker">
         <font>
            <Font size="20.0" />
         </font>
      </Label>
      <TextArea layoutX="64.0" layoutY="81.0" prefHeight="279.0" prefWidth="503.0" text="*** このアプリについて ***&#10;主に、問題の作成、編集、削除、コピー&#10;を行うアプリです。&#10;&#10;ぜひ、あなたの勉強に活用してみてください。&#10;&#10;This app is Beta ver 1.0&#10;© Powered by hoge.net &#10;">
         <font>
            <Font size="18.0" />
         </font>
      </TextArea>
      <Label fx:id="displayName" layoutX="357.0" layoutY="31.0" text="ようこそ、○○さん" />
      <Button fx:id="myList" layoutX="64.0" layoutY="46.0" mnemonicParsing="false" onAction="#onClickedMyList" text="myList" />
      <Button fx:id="latestShow" layoutX="128.0" layoutY="46.0" mnemonicParsing="false" onAction="#onClickedLatestShow" text="latestShow" />
      <Button fx:id="doTest" layoutX="213.0" layoutY="46.0" mnemonicParsing="false" onAction="#OnClickedDoTest" text="DoTest" />
   </children>
   <padding>
      <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
   </padding>
</Pane>

5.7. SubController.java

SubController.java
package application.home;

import application.Screen;
import application.main.MainController;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Label;

public class SubController {

	@FXML
    private Button backButton;

    @FXML
    private Label displayName;
    
    @FXML
    private Button doTest;

    @FXML
    private Button latestShow;

    @FXML
    private Button myList;
    
    // hold user
    String current_user_name;

    @FXML
    void OnclickedBackButton(ActionEvent event) {
        backButton.getScene().getWindow().hide();           //画面を閉じる
        Screen screen = new Screen();                       //画面を開く(メソッド呼び出し)の準備
        screen.transitionScreen("main/MainScreen.fxml", "Login Form");  //画面を開く
    }
    
    public void getUserName() {
    	MainController mainC = new MainController();
    	String name = mainC.getCurrent_user_name();
    	current_user_name = name; 
    }
    
    @FXML
    void onClickedLatestShow(ActionEvent event) {
    	latestShow.getScene().getWindow().hide();           //画面を閉じる
        Screen screen = new Screen();                       //画面を開く(メソッド呼び出し)の準備
        screen.transitionScreen("aaa/aaa.fxml", "toAAA");  //画面を開く
    }
    
    @FXML
    void OnClickedDoTest(ActionEvent event) {
    	doTest.getScene().getWindow().hide();           //画面を閉じる
        Screen screen = new Screen();                       //画面を開く(メソッド呼び出し)の準備
        screen.transitionScreen("bbb/bbb.fxml", "toBBB");  //画面を開く
    }

    @FXML
    void onClickedMyList(ActionEvent event) {
    	myList.getScene().getWindow().hide();           //画面を閉じる
        Screen screen = new Screen();                       //画面を開く(メソッド呼び出し)の準備
        screen.transitionScreen("ccc/ccc.fxml", "toCCC");  //画面を開く
    }

    @FXML
    void initialize() {
        assert backButton != null : "fx:id=\"backButton\" was not injected: check your FXML file 'subScreen.fxml'.";
        assert doTest != null : "fx:id=\"doTest\" was not injected: check your FXML file 'subScreen.fxml'.";
        assert myList != null : "fx:id=\"myList\" was not injected: check your FXML file 'subScreen.fxml'.";
        assert latestShow != null : "fx:id=\"latestShow\" was not injected: check your FXML file 'subScreen.fxml'.";
        assert doTest != null : "fx:id=\"doTest\" was not injected: check your FXML file 'subScreen.fxml'.";
    }
}

5.8. Screen.java

自分で作るファイルです

Screen.java
package application;

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

public class Screen {
    public void transitionScreen(String fxmlName, String fxmlTitle) {
        try {
            //FXMLからのシーングラフの読み込み
            FXMLLoader loader = new FXMLLoader(getClass().getResource(fxmlName));
            Parent root = loader.load();

            //シーングラフのルートノードを設定したシーンの作成
            Scene scene = new Scene(root, 1000, 600);
            //ステージへのシーンの設定
            Stage stage = new Stage();

            stage.setScene(scene);
            stage.setTitle(fxmlTitle);
            stage.show();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

5.9. Java Application として実行

VM引数に

--module-path "(ダウンロードしたJavaFXのlibフォルダへのフルパス)" --add-modules javafx.controls,javafx.fxml

を追加して実行してください

MainController.javaのOnClickedNextButtonの処理を書いて、
画面遷移できたと思います。

.fxmlを作る > Scene Builderで画面を作って、コンテナにidやActionをつける > Controllerで制御メソッドやフィールドを追加して処理を書く

のサイクルでどんどん画面ができていくと思います。

6. おわり

以上で記事を終了しますが、初学者ゆえとりあえず動く状態でこの記事を書いてますので
誤った情報や重複した内容がありましたら申し訳ありません。

以降のTableViewなど機能を追加するにあたりよさげな資料をここに挙げます。

RandomCode - TableView-TableColumn

thenewboston - JavaFX Java GUI Tutorial - 12 - ChoiceBox (Drop Down Menu)

RandomCode - Toggle Button

4
2
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
4
2