読者です 読者をやめる 読者になる 読者になる

JavaFX で Google guice によって FXMLLoader のロードを補助する

Java

JavaFX の Controller (←この呼び方が個人的には嫌い、MVCモデルの Cなんだろうけど)のファクトリの
コールバックに、Google guice でのインジェクションを行う方法は、とても有効な手段だと思う。

前回の投稿、
JavaFX の画面遷移、簡単に書く。 - Oboe吹きプログラマの黙示録

で書いた Controller クラスと fxml 名を指定して画面遷移させるメソッド setPage と書いたものは、以下のように
Google guice でのインジェクトの約束が書ける。。

======
この投稿後、あまり良くないと思って、結局、、
JavaFX のイニシャライズ処理を Google guice で整理 - Oboe吹きプログラマの黙示録

を書くはめになった。
======

/* @see javafx.application.Application#start(javafx.stage.Stage) */
@Override
public void start(Stage primaryStage) throws Exception{
   stage = primaryStage;
   setPage(StartPage.class, "start.fxml");
}
public void setPage(final Class<?> cls, String fxml, Object...params) throws Exception{
   Injector injector = Guice.createInjector(new AbstractModule(){
      @Override
      protected void configure(){
         // TODO bind 定義する
      }
   });
   FXMLLoader loader = new FXMLLoader(cls.getResource(fxml));
   loader.setControllerFactory(new Callback<Class<?>, Object>(){
      @Override
      public Object call(Class<?> type){
         return injector.getInstance(cls);
      }
   });
   Scene scene = new Scene((Parent)loader.load());
   BasePage page = (BasePage)loader.getController();
   page.setApp(this);
   page.loadParameter(params);
   stage.setTitle(WINDOW_TITLE);
   stage.setScene(scene);
   stage.show();
}

FXMLLoader loader の実行は、引数なしの load() の実行になる。
Callback の call メソッドのパラメータ type でなくて、setPage で渡される class を指定する!

Mainクラスの全体は以下のようになる。

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;
import javafx.util.Callback;
/**
 * MainApp
 */
public class MainApp extends Application{
   static Logger logger = LoggerFactory.getLogger(MainApp.class);
   static String WINDOW_TITLE  = "fxtest2";
   private Stage stage;

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

   /* @see javafx.application.Application#start(javafx.stage.Stage) */
   @Override
   public void start(Stage primaryStage) throws Exception{
      stage = primaryStage;
      setPage(StartPage.class, "start.fxml");
   }
   public void setPage(final Class<?> cls, String fxml, Object...params) throws Exception{
      Injector injector = Guice.createInjector(new AbstractModule(){
         @Override
         protected void configure(){
            // TODO bind 定義する
         }
      });
      FXMLLoader loader = new FXMLLoader(cls.getResource(fxml));
      loader.setControllerFactory(new Callback<Class<?>, Object>(){
         @Override
         public Object call(Class<?> type){
            return injector.getInstance(cls);
         }
      });
      Scene scene = new Scene((Parent)loader.load());
      BasePage page = (BasePage)loader.getController();
      page.setApp(this);
      page.loadParameter(params);
      stage.setTitle(WINDOW_TITLE);
      stage.setScene(scene);
      stage.show();
   }
}

setPage の引数、Object...params 画面遷移時に渡すパラメータ、 page.loadParameter(params);
と書いてはいるが、
guice のインジェクションとして、上の // TODO bind 定義する
で、パラメータ渡しを書く方法もあるだろう。
すると、loadParameter というメソッドは、不要になってくるはずだ。。