1. ホーム
  2. javafx

[解決済み】 パラメータの受け渡し JavaFX FXML

2022-04-10 16:11:34

質問

javafxでセカンダリウィンドウにパラメータを渡すにはどうすればよいですか?また、対応するコントローラと通信する方法はありますか?

例えば ユーザは TableView をクリックすると、新しいウィンドウが開き、その顧客の情報が表示されます。

Stage newStage = new Stage();
try 
{
    AnchorPane page = (AnchorPane) FXMLLoader.load(HectorGestion.class.getResource(fxmlResource));
    Scene scene = new Scene(page);
    newStage.setScene(scene);
    newStage.setTitle(windowTitle);
    newStage.setResizable(isResizable);
    if(showRightAway) 
    {
        newStage.show();
    }
}

newStage が新しいウィンドウになります。問題は、コントローラが顧客の情報を探す場所を教える方法が見つからないことです(idをパラメータとして渡します)。

何かアイデアはありますか?

解決方法は?

MVCの使用

この回答のほとんどは、呼び出し元のクラスからコントローラーにパラメータを渡すための直接呼び出しに焦点を当てています。

その代わりに、呼び出し側とコントローラ側を切り離し、 setable および listenable プロパティを持つモデルクラスを含むより一般的なアーキテクチャを使用してコントローラ間の通信を実現したい場合は、以下の基本概要をご覧ください。

推奨するアプローチ

この回答では、FXMLコントローラにパラメータを渡すためのさまざまなメカニズムを列挙しています。

小さなアプリケーションでは、呼び出し元からコントローラへ直接パラメータを渡すことを強くお勧めします。

より大規模で複雑なアプリケーションの場合、以下のような方法で調査する価値があります。 依存性インジェクション または イベントバス のメカニズムをアプリケーションに組み込むことができます。

呼び出し元からコントローラへの直接のパラメータ渡し

FXML ローダーインスタンスからコントローラを取得し、 そのコントローラのメソッドを呼び出して必要なデータ値で初期化することにより、 FXML コントローラにカスタムデータを渡します。

以下のコードのようなものです。

public Stage showCustomerDialog(Customer customer) {
  FXMLLoader loader = new FXMLLoader(
    getClass().getResource(
      "customerDialog.fxml"
    )
  );

  Stage stage = new Stage(StageStyle.DECORATED);
  stage.setScene(
    new Scene(loader.load())
  );

  CustomerDialogController controller = loader.getController();
  controller.initData(customer);

  stage.show();

  return stage;
}

...

class CustomerDialogController {
  @FXML private Label customerName;
  void initialize() {}
  void initData(Customer customer) {
    customerName.setText(customer.getName());
  }
}

サンプルコードに示すように、新しいFXMLLoaderが構築されます。 new FXMLLoader(location) . ロケーションはURLで、FXMLリソースからこのようなURLを生成することができます。

new FXMLLoader(getClass().getResource("sample.fxml"));

FXMLLoaderのスタティックロード関数を使用しないように注意してください。

FXMLLoaderインスタンス自体は、ドメインオブジェクトについて何も知りません。 アプリケーション固有のドメインオブジェクトをFXMLLoaderのコンストラクタに直接渡すのではなく、以下のようにします。

  1. 指定された場所にあるfxmlマークアップに基づいてFXMLLoaderを構築します。
  2. FXMLLoaderインスタンスからコントローラを取得します。
  3. 取得したコントローラのメソッドを呼び出して、コントローラにドメインオブジェクトへの参照を提供します。

このブログ(別のライターによる)では、別の、しかし似たようなものを紹介しています。 .

FXMLLoaderにControllerを設定する

CustomerDialogController dialogController = 
    new CustomerDialogController(param1, param2);

FXMLLoader loader = new FXMLLoader(
    getClass().getResource(
        "customerDialog.fxml"
    )
);
loader.setController(dialogController);

Pane mainPane = loader.load();

新しいコントローラをコードで作成し、呼び出し元から必要なパラメータをコントローラコンストラクタに渡すことができます。 コントローラを作成したら、それを FXMLLoader のインスタンスに設定します。 以前 を呼び出すと load() インスタンス メソッドを使用します。

ローダーにコントローラを設定する場合(JavaFX 2.xの場合)は、ローダーと同時に fx:controller 属性で指定します。

の制限により fx:controller を定義しているため、個人的にはFXMLLoaderにコントローラを設定するよりも、FXMLLoaderからコントローラを取得する方が好みです。

コントローラに外部の静的メソッドからパラメータを取得させる

この方法は、Sergeyの回答で例証されています。 Javafx 2.0 ハウツー Controller.java ファイル内の Application.getParameters() .

依存性注入を使用する

FXMLLoaderはGuice、Spring、Java EE CDIなどの依存性注入システムをサポートし、FXMLLoaderにカスタムコントローラファクトリを設定することができます。 これは、それぞれの依存性注入システムによって注入された依存値を持つコントローラのインスタンスを作成するために使用できるコールバックを提供します。

JavaFXアプリケーションとSpringによるコントローラの依存性注入の例が回答として提供されています。

本当に素晴らしく、きれいな依存性注入のアプローチは、以下のような例です。 afterburner.fx フレームワーク というサンプルで エアハックスアプリケーション afterburner.fxはJEE6に依存しています。 javax.inject を使用して、依存性注入を実行します。

イベントバスを利用する

FXMLの仕様策定と実装を行ったGreg Brownは、しばしばイベントバスの利用を提案しています。 イベントバス FXMLのインスタンス化されたコントローラと他のアプリケーションロジックとの間の通信に使用されます。

<ブロッククオート

EventBusは、POJOがお互いを参照することなく、JVMのどこでも通信できるようにするアノテーションを持つ、シンプルで強力なパブリッシュ/サブスクライブAPIです。

フォローアップ Q&A

最初のメソッドでは、なぜステージを返しているのですか?return stage;の直前にshow();を与えているので、このメソッドはvoidにもなりえます。Stageを返すことでどのような使い方ができるのでしょうか?

それは機能的な問題解決です。ステージが返されるのは showCustomerDialog このクラスは、メインウィンドウのボタンをクリックするとステージが隠れるなどの処理を、後で行いたいかもしれません。 オブジェクト指向の解決策としては、CustomerDialogオブジェクトの中に機能とステージの参照をカプセル化するか、CustomerDialogがStageを継承するようにすることができます。 FXML、コントローラ、モデルデータをカプセル化したカスタムダイアログのオブジェクト指向インターフェースの完全な例は、この回答の範囲外ですが、作成する気がある人にとっては、価値のあるブログ記事になるでしょう。


StackOverflow のユーザー名による追加情報です。 dzim

Spring Bootの依存性注入の例

How to do it "The Spring Boot Way"の問題で、JavaFX 2の議論がありましたが、添付のパーマリンクでアンサーしています。 この方法は今でも有効で、2016年3月にSpring Boot v1.3.3.RELEASEでテストしています。 https://stackoverflow.com/a/36310391/1281217


時には、結果を呼び出し元に戻したい場合もあるでしょう。その場合は、関連する質問に対する答えをチェックすることができます。