2016-04-21 3 views
0

これはnewb-swimming-upstreamのケースですが、...JavaFX-8では、FXML/FXMLLoaderを使用して作成されていないノードにコントローラを動的に追加できますか?

FXMLファイルでは、属性の1つがコントローラを識別します。コントローラと識別されたメソッドがロード中にノードにバインドされていると仮定しています(コントローラインスタンスがインスタンス化され、そのメソッドがFXMLで識別されるリスナーとしてバインドされています)。

コントローラインスタンスを、FXMLLoader経由で手続き的に作成されたJavaFXノード(TableViewなど)にプログラムで関連付ける方法はありますか?

答えて

1

私が正しく理解していれば、FXMLLoaderをインスタンス化するのではなく、Javaコードでコントローラインスタンスを定義する必要があります。

load()に電話する前にFXMLLoadersetControllerを呼び出すことでこれを行うことができます。あなたがこのテクニックを使用する場合は、使用してはならない

MyController controller = new MyController(); 
FXMLLoader loader = new FXMLLoader(getClass().getResource("path/to/fxml")); 
loader.setController(controller); 
Parent root = loader.load(); 

:これはあなたがFXMLLoaderインスタンスを作成し、インスタンスload()メソッドを呼び出す必要があります意味し、静的load(URL)メソッドを呼び出してはならないことに注意してくださいfx:controller属性をFXMLファイルのルート要素に追加します。

これにより、好きなようにコントローラをインスタンス化することができます。パラメータを取るコンストラクタを持つコントローラクラスがあれば、ここでそれらを使うことができます(デフォルトのメカニズムで使われるコントローラには、ゼロ引数のコンストラクタが必要です)。

より高度が関連情報:

関連技術、おそらくより特殊なユースケースのために、FXMLLoaderにコントローラファクトリを設定することです。コントローラファクトリは、Class<?>fx:controller属性で定義されたもの)をオブジェクト(コントローラ)にマップする関数です。これは基本的にコントローラがインスタンス化される方法(通常はリフレクションを使用して)をプログラマチックに制御します。

public class Model { /* ... */ } 

などのモデルクラスと、モデル参照をコンストラクタパラメータとして使用するいくつかの異なるコントローラクラスがあります。通常は、同じモデルインスタンスを使用してすべてのコントローラに渡す必要があります。次のようにだから、コントローラーファクトリを定義することができます。

Model model = new Model(); 
Callback<Class<?>, Object> controllerFactory = type -> { 
    try { 
     // look for a constructor with a single parameter of type Model: 
     for (Constructor<?> c : type.getConstructors) { 
      if (c.getParameterCount() == 1 && c.getParameterTypes()[0] == Model.class) { 
       return c.newInstance(model); 
      } 
     } 
     // no constructor found, just invoke no-arg constructor as in default: 
     return type.newInstance(); 
    } catch (Exception e) { 
     throw new RuntimeException(e); 
    } 
}; 

を次に、あなたがあなたのFXMLLoader上のコントローラの工場(複数可)を設定することができます。

FXMLLoader loader = new FXMLLoader(getClass().getResource("path/to/fxml")); 
loader.setControllerFactory(controllerFactory); 
Parent root = loader.load(); 

この技術の別の用途は、依存性注入と連動していますSpringやGuiceなどのフレームワークDIフレームワークを構成してコントローラをインスタンス化し、モデルインスタンスをモデルインスタンスに挿入する場合は、コントローラファクトリを使用してFXMLLoaderがコントローラインスタンスをフレームワークから取得できるようにすることができます。例えば。

ApplicationContext context = ... ; 

FXMLLoader loader = new FXMLLoader(getClass().getResource("path/to/fxml")); 
loader.setControllerFactory(context::getBean); 
Parent root = loader.load(); 

やGuiceのと::春と

Injector injector = Guice.createInjector(...); 

FXMLLoader loader = new FXMLLoader(getClass().getResource("path/to/fxml")); 
loader.setControllerFactory(injector::getInstance); 
Parent root = loader.load(); 
+0

私は不明でした。私はFXMLLoader(すなわち、FXMLファイルなし)を使用していませんが、単純にノードを手渡しました。 「明白な答え」は、「彼らが意図したとおりにFXMLを使用する」ことですが、それ以外の方法があるかどうかを知りたいだけでした。 これはちょっとしたハックかもしれませんが、ノードを生成するときにコントローラーインスタンスをインスタンス化してから、ノードにハンドラーを戻す前にイベントハンドラーをノードに登録することができます。 – SoCal

+0

何をすればいいですか?コードでコントロールを作成する場合、私はあなたがしたいことを理解していません。質問を編集して、意味を示すコードを追加します。 –

0

だから、これは私がGUIの開発で新しいものの(a)の結果であると思われ、JavaFXのを使用しての(B)にも新しいです。

あなたは、その後に調製すること、(すなわち、無FXMLファイル、FXMLLoaderを用いない)非FX方法でのJavaFXコンポーネントを使用して主張しようとしている場合は、一番下の行は...

ように見えますイベントハンドラを非FXスタイルで登録する(ノードの構築中に手続き的に追加する)。