web-dev-qa-db-ja.com

FXMLコントローラークラスへのアクセス

メインアプリケーションまたは他の段階から画面上の情報を更新するために、いつでもFXMLコントローラークラスと通信したいと思います。

これは可能ですか?私はそれをする方法を見つけていません。

静的関数を使用する方法もありますが、フォームのコントロールにアクセスすることはできません。

何か案は?

57
betaman

FXMLLoaderからコントローラーを取得できます

FXMLLoader fxmlLoader = new FXMLLoader();
Pane p = fxmlLoader.load(getClass().getResource("foo.fxml").openStream());
FooController fooController = (FooController) fxmlLoader.getController();

メインステージに保存し、getFooController()getterメソッドを提供します。
他のクラスまたはステージから、ロードされた「foo.fxml」ページを更新する必要があるたびに、コントローラーからそれを要求します。

getFooController().updatePage(strData);

updatePage()は次のようになります。

// ...
@FXML private Label lblData;
// ...
public void updatePage(String data){
    lblData.setText(data);
}
// ...

fooControllerクラス内。
このようにして、他のページのユーザーは、Label lblDataがどこにあるのかなど、ページの内部構造を気にしません。

https://stackoverflow.com/a/10718683/682495 もご覧ください。 JavaFX 2.2では、FXMLLoaderが改善されています。

96
Uluk Biy

受け入れられた答えを明確にし、JavaFXを初めて使用する他の人の時間を少し節約するためだけに:

JavaFX FXMLアプリケーションの場合、NetBeansは次のようにメインクラスで開始メソッドを自動生成します。

_@Override
public void start(Stage stage) throws Exception {
    Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));

    Scene scene = new Scene(root);

    stage.setScene(scene);
    stage.show();
}
_

ここで、コントローラークラスにアクセスするために必要なことは、FXMLLoaderのload()メソッドを静的実装からインスタンス化された実装に変更するだけです。その後、インスタンスのメソッドを使用してコントローラーを取得できます。 :

_//Static global variable for the controller (where MyController is the name of your controller class
static MyController myControllerHandle;

@Override
public void start(Stage stage) throws Exception {
    //Set up instance instead of using static load() method
    FXMLLoader loader = new FXMLLoader(getClass().getResource("FXMLDocument.fxml"));
    Parent root = loader.load();

    //Now we have access to getController() through the instance... don't forget the type cast
    myControllerHandle = (MyController)loader.getController();

    Scene scene = new Scene(root);

    stage.setScene(scene);
    stage.show();
}
_
17
DatuPuti

別の解決策は、コントローラクラスからコントローラを設定することです。

public class Controller implements javafx.fxml.Initializable {

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        // Implementing the Initializable interface means that this method
        // will be called when the controller instance is created
        App.setController(this);
    }

}

これは、ローカルリソースなどを適切に処理する完全に機能するFXMLLoaderインスタンスを作成するためにコードが多少面倒なので、私が使用したいソリューションです

@Override
public void start(Stage stage) throws Exception {
    Parent root = FXMLLoader.load(getClass().getResource("/sample.fxml"));
}

versus

@Override
public void start(Stage stage) throws Exception {
    URL location = getClass().getResource("/sample.fxml");
    FXMLLoader loader = createFXMLLoader(location);
    Parent root = loader.load(location.openStream());
}

public FXMLLoader createFXMLLoader(URL location) {
    return new FXMLLoader(location, null, new JavaFXBuilderFactory(), null, Charset.forName(FXMLLoader.DEFAULT_CHARSET_NAME));
}
7
Caleb

メイン画面からのオブジェクトの読み込みで、見つけて動作したデータを渡す方法の1つは、ルックアップを使用して、後でコントローラークラスから取得できる非表示ラベル内にデータを設定することです。このような:

Parent root = FXMLLoader.load(me.getClass().getResource("Form.fxml"));
Label lblData = (Label) root.lookup("#lblData");
if (lblData!=null) lblData.setText(strData); 

これは機能しますが、より良い方法が必要です。

2
betaman