✍️

備忘録:JavaFX+GuiceでFXMLコントローラークラスにインジェクションする方法

2024/07/14に公開

JavaFX+Guice で FXML コントローラークラスにインジェクションする方法の備忘録。

1. 動作環境

  • macOS 14.5
  • Java 21.0.3
  • JavaFX 21.0.3
  • Guice 7.0.0

2. 概要

FXMLLoader クラスに GuiceInjector を使ったコントローラーファクトリーを指定してロードする。

3. サンプル

ボタンを押したらリストに日時を追加する。
サンプル画面

ファイル名 概要
App.java JavaFX メインクラス
JavaFXGuiceMain.fxml FXML ファイル
JavaFXGuiceMainController.java FXML のコントローラークラス
BusinessLogic.java ビジネスロジックインターフェース
BusinessLogicImpl.java BusinessLogic.java の実装クラス
App.java
package org.javafxguice;

import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;

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

public class App extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {
        /*
         * GuiceのInjectorの生成
         */
        Injector injector = Guice.createInjector(new AbstractModule() {

            @Override
            protected void configure() {
                /*
                 * DIの設定
                 */
                bind(BusinessLogic.class).to(BusinessLogicImpl.class);
            }
        });

        FXMLLoader loader = new FXMLLoader(
                this.getClass().getResource("JavaFXGuiceMain.fxml"), null, null,
                injector::getInstance); // コントローラーファクトリーの指定
        Parent root = loader.load();

        primaryStage.setTitle("JavaFX and Guice");
        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }

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

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

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.layout.VBox?>

<VBox alignment="TOP_CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="300.0" prefWidth="300.0" spacing="10.0"
   xmlns="http://javafx.com/javafx/21"
   xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.javafxguice.JavaFXGuiceMainController">
   <children>
      <ListView fx:id="fxListView" prefHeight="200.0" prefWidth="200.0" VBox.vgrow="ALWAYS" />
      <Button fx:id="fxButton" mnemonicParsing="false" text="ボタン" />
   </children>
   <padding>
      <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
   </padding>
</VBox>
JavaFXGuiceMainController.java
package org.javafxguice;

import com.google.inject.Inject;

import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;

public class JavaFXGuiceMainController {

    @FXML
    private Button fxButton;

    @FXML
    private ListView<String> fxListView;

    private final BusinessLogic businessLogic;

    /*
     * Guiceによるコンストラクターインジェクション
     */
    @Inject
    JavaFXGuiceMainController(BusinessLogic businessLogic) {
        this.businessLogic = businessLogic;
    }

    /*
     * コントローラーの初期設定
     */
    public void initialize() {

        /*
         * ボタンアクションの設定
         */
        fxButton.setOnAction(event -> {
            /*
             * ビジネスロジックの結果をListViewに追加
             */
            String dateTimeString = businessLogic.getDateTimeString();
            fxListView.getItems().add(dateTimeString);
        });
    }

}
BusinessLogic.java
package org.javafxguice;

public interface BusinessLogic {

    public String getDateTimeString();

}
BusinessLogicImpl.java
package org.javafxguice;

import java.time.LocalDateTime;

public class BusinessLogicImpl implements BusinessLogic {

    @Override
    public String getDateTimeString() {
        /*
         * ビジネスロジックの実装
         */
        return LocalDateTime.now().toString();
    }

}

Discussion