LoginSignup
33

More than 5 years have passed since last update.

【FXML利用】JavaFX8でControllerを疎結合に保って、画面遷移する方法

Last updated at Posted at 2015-04-24

この記事で紹介すること

  • JavaFX8でFXMLを使ったアプリケーションで画面遷移をする方法
  • 上記を実現するにあたり、できるだけControllerを疎結合にする方法

例のごとくJavaFX8もJava8も初めての経験なので、
「今のところこういう感じがよさそう」と思った内容を記載しておきます。
色々ご指摘頂けると嬉しいです。

前置き

ポイントとなる部分だけコードをなんとなく書いているので、
JavaFX(バージョン8)で画面遷移どうするんだろう、とか、
Controller同士が疎結合にならない、、、とかいうお悩みの方が対象の内容になります。

問題1:JavaFXで画面遷移ってどうするの?

ShowされたStageにSceneをセットするだけです。
※StegeにSceneをセットしてShowするでも良いです。

問題2:Stage、ってあのメインクラスの?何か嫌な予感。。

すみません。これ良いわっていうほどの解決策ではないかもしれません。
やっぱStageはメインクラスで多少がちゃがちゃして、というのはしょうがない気がします。

ちょっと不安に思わせてしまったかもですが、
実際にコードを見てみましょう。

メインクラス

Applicationを継承したメインクラスです。

説明が長くなりそうだったので、
他のControllerから取得するためのStageを無理やりpublic staticにしていますが、
皆さんがやるときは、ぜひ別途情報共有クラスを作って下さい。

SampleMain.java
public class SampleMain extends Application{

    // 他のControllerから取得するためのStage(できれば別クラスを用意する)
    public static Stage presentStage;

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

    @Override
    public void start(Stage stage) throws Exception {
        presentStage = stage;

        // タイトル
        stage.setTitle("Sample");

        // sceneの作成(nullですので中身ないです)
        Scene scene = new Scene(new Pane());
        stage.setScene(scene);

        // 最初の画面
        LoginController.getInstance().show();

        // 表示
        stage.show();
    }

}

それぞれのControllerの構成

メインから呼び出した、最初のログイン画面というていで見てください。
他のControllerも共通化しない場合は同じ構成を持つことになります。

ポイントはSceneをシングルトンにして、
メインクラスで設定したStageを持ってきてShowメソッドでセットすることです。

ちなみにインスタンスはFXMLのコントローラークラスが指定されている状態なら
load()した後に、getController()で取れます。
※その代わりこのアクセス方法の場合、コンストラクタはprivateにできません。注意しないと、、、

LoginController.java
public class LoginController {
    /**
    * instance(singleton)
    */
    private static final LoginController instance;
    /**
     * Scene(singleton)
     */
    private static final Scene SCENE;
    static {
        FXMLLoader fxmlLoader = new FXMLLoader(ClassLoader.getSystemResource("login.fxml"));
        try {
            fxmlLoader.load();
        } catch (IOException e) {
            // loggerを使って何かしら出すほうがいいですね。手抜きですみません
            e.printStackTrace();
        }
        Parent parent = fxmlLoader.getRoot();
        Scene s = new Scene(parent);
        s.setFill(Color.TRANSPARENT);
        SCENE = s;
        instance = fxmlLoader.getController();
    }

    /**
     * singletonのインスタンスを返す
     * @return instance
     */
    public static LoginController getInstance() {
        return instance;
    }

    /**
     * 表示する
     */
    public void show() {
        SampleMain.presentStage.setScene(SCENE);
    }

    @FXML
    public void onClick(ActionEvent event) {
        // クリック時の処理とか色々して~~~次のページ表示
        FirstContent.getInstance().show();
    }
}

結果

これを全画面(Controller)でやっていくと、
FXMLとControllerは1対1、
そしてController同士は別のControllerを呼び出したくてもすぐ切り替えられる、
ということになります。
やっと実用的な感じがしてきました。

あとがき

2つしか画面使わないアプリケーションだったので疎結合に書くならこんな感じかなぁと思いましたが、
複数ある場合は、上手く共通化した方がよさそうです。

それにしてもJavaでGUI作れるのは凄く良いです。
処理は簡単に書けるし、DBアクセスも楽チン!
gradle使ってすぐ共有できるし、exeにも変換できるライブラリがある!

まだ微妙な面もありますが、
少しずつ使う人が増えて情報が整理されると良いなーと思います。」

余談ですが、JavaFXではScene BuilderというGUI作成を簡単にするやつが絶対必須です!
ワシはXML直に書きたいんやってお方以外はぜひ使ってみてください。

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
33