ページ

2013年3月31日日曜日

JavaFX - FXMLファイルでViewを定義したときのControllerの設定(2)

前回は、FXMLファイルでViewを定義したときのControllerの設定についてみていきました。今回は、FXMLファイルを読み込んでControllerを取得するユーティリティクラスを作成してみたいと思います。

名称としては、FXControllerとして作成していきます。

まずは、FXMLファイルのfx:controller属性で、Controllerを指定した場合を考えていきます。この場合、FXMLファイルのURLを指定して、以下のようにControllerが取得できるようにします。

SimpleViewController controller = FXController.<SimpleViewController>from(location)
    .load();

ResourceBundleを指定したい場合は、以下のように指定できるようにします。

SimpleViewController controller = FXController.<SimpleViewController>from(location)
    .with(resources)
    .load();

また、ResouceBundleの代わりに、以下のようにリソースバンドルの基底名を指定できるようにします。

SimpleViewController controller = FXController.<SimpleViewController>from(location)
    .withResourceOf(resourceBaseName)
    .load();>

fx:controller属性で指定しているControllerのクラスの指定は、以下のように指定できるようにもします。

SimpleViewController controller = FXController.of(SimpleViewController.class)
    .from(location)
    .load();

次に、FXMLファイルのfx:controller属性を指定しなかった場合を考えていきます。この場合、ControllerのインスタンスとURLを指定して、以下のようにFXMLファイルを読み込めるようにします。

SimpleViewController controller = FXController.of(new SimpleViewController())
    .from(loacation)
    .load();

また、以下のように、ResouceBundle、あるいは、リソースバンドルの基底名を指定できるようにします。

SimpleViewController controller = FXController.of(new SimpleViewController())
    .from(loacation)
    .with(resources)
    .load();
SimpleViewController controller = FXController.of(new SimpleViewController())
    .from(loacation)
    .withResourceOf(resourceBaseName)
    .load();

FXMLファイル名の指定については、Controllerのクラスの定義に、FXMLLocationアノテーションで指定できるようにもします。指定する場合は、ClassのgetResourceメソッドに指定する場合と同じ名称を指定するようにします。

@FXMLLocation("SimpleView.fxml")
public class SimpleViewController {
}

この場合、以下のようにして読み込むようにします。

SimpleViewController controller = FXController.of(new SimpleViewController())
    .fromDefaultLocation()
    .load();

また、FXMLLocationアノテーションで指定していない場合は、次の命名規則で、FXMLファイルを検索するようにします。

Controllerと同じパッケージで、Controllerの名称から末尾の「Controller」を除いた名称に「.fxml」をつけたファイル

ofメソッドでControllerのインスタンスを指定したときに、そのインスタンスが、javafx.scene.Sceneクラス、あるいは、javafx.scene.Nodeクラスのサブクラスの場合は、javafx.fxml.FXMLLoaderクラスのsetRootメソッドにControllerのインスタンスを設定してから読み込むようにして、FXMLファイルをfx:root要素で定義した場合にも対応できるようにします。

public class SimpleControl extends StackPane {
    public SimpleControl() {
        initializeComponent();
    }

    protected void initializeComponent() {
        FXController.of(this).fromDefaultLocation.load();
    }
}

あと、個人的には、依存性の注入にgoogle-guiceを使いたいので、以下のように、com.google.inject.Injectorの指定もできるようにしておきます。

SimpleViewController controller = FXController.of(SimpleViewController.class)
    .using(injector)
    .from(location)
    .load();

この場合も、以下のように、アノテーション、あるいは、命名規則で、FXMLファイルを検索できるようにします。

SimpleViewController controller = FXController.of(SimpleViewController.class)
    .using(injector)
    .fromDefaultLocation()
    .load();

ResourceBundle、あるいは、リソースバンドルの基底名についても、指定できるようにしておきます。

SimpleViewController controller = FXController.of(SimpleViewController.class)
    .using(injector)
    .fromDefaultLocation()
    .with(resources)
    .load();
SimpleViewController controller = FXController.of(SimpleViewController.class)
    .using(injector)
    .fromDefaultLocation()
    .withResourceOf(resourceBaseName)
    .load();

さらに、ofメソッドに、Controllerのインスタンスを指定できるようにもしておきます。

SimpleViewController controller = FXController.of(new SimpleViewController())
    .using(injector)
    .fromDefaultLocation()
    .load();

また、com.google.inject.Injectorについては、usingメソッドで毎回指定せず、以下のようにstaticメソッドで指定し、常にそこで指定したcom.google.inject.Injectorを用いてインスタンスを取得できるようにもします。

FXController.setDefaultInjector(injector);

SimpleViewController controller = FXController.of(SimpleViewController.class)
    .fromDefaultLocation()
    .load();

以上のようなことができるユーティリティクラスを作成したいと思います。