2016-10-25 9 views
0

Javaで書かれたコントローラクラスの横にFXMLを使用するJavaFXアプリケーションがあります。 Javaコントローラでは、FXML Node要素が初期化されるまで(それ以外の場合はNullPointerExceptionが発生するまで)操作しないように注意する必要があります。これはinitializeメソッドが実行されるまで保証されません。FXML: "初期化後に実行"

コントローラは、このようFXMLファイルに設定されています:

<Pane fx:controller="Controller" ...> 
... 
</Pane> 

そしてここJavaファイルのコントローラだだから私は自分自身は、この多くのことをやって見つけます。

class Controller{ 
    @FXML 
    Pane aPane; 
    int globalValue; 

    public void setSomething(int value){ 
     globalValue = value; 
     if(!(aPane == null)){ //possibly null if node not initialized yet 
      aPane.someMethod(globalValue) 
     } 
    } 

    @FXML 
    void initialize(){ 
     aPane.someMethod(globalValue) //guaranteed not null at this point 
    } 


} 

これは機能しますが、ぎこちない繰り返しです。 initializeが呼び出される前にsetSomethingメソッドが呼び出された場合のためにglobalValue属性を作成する必要があります。メソッドの操作がinitializeの操作と同じであることを確認する必要があります。

確かにこれを行うためのよりエレガントな方法があります。 JavaFXにはPlatform.runlater(...)メソッドがあり、何かがメインのアプリケーションスレッド上で実行されることが保証されています。 Perhpasには、初期化まで待つか、または初期化がすでに行われていればすぐに実行されるようなものがあります(Platform.runAfterInitialize(...))。それを行う別の方法がある場合は、私は提案に開放しています。

+0

をあなたが設定されています:単にFXMLLoaderにコントローラを渡す前に、コントローラ上のsetメソッドを呼び出して回避することで、任意の@FXML -annotatedフィールドは、コントローラのパブリックメソッドで初期化されていると仮定できることを意味しますコードからの 'FXMLLoader'のコントローラ?そうでない場合は、 'FXMLLoader'によって' initialize() 'が呼び出される前に' setSomething(...) 'を呼び出す方法がありません。もう少し文脈を与えることができますか? –

+0

私はquesitonにいくつかの説明を加えました。私は最初に 'FXMLLoader'を作成していて、' setController'メソッドを使ってこの問題を発見しました。今私はコントローラにアクセスするために '@ FXML'で注釈が付けられた収容クラスの' Controller'オブジェクトを使用しています。そのようにしたらこの問題は存在しませんか? –

+0

回答を参照してください。 'fx:controller'を使うと、インスタンス化と' @ FXML'-annotatedフィールドの間でコントローラインスタンスにアクセスする方法がありません。 –

答えて

3

あなたはfx:controller="Controller"とFXMLファイルでコントローラを指定する場合、あなたはFXMLLoader.load(...)を呼び出し、FXMLLoader

  1. はありません
  2. は(事実上)その呼び出すことによってControllerのインスタンスを作成し、FXMLファイルを解析します-argコンストラクタ(または、高度な使い方でコントローラファクトリを設定した場合はコントローラファクトリを呼び出す)
  3. は、要素に対応するUI要素をFXMLファイルに作成します。
  4. は任意のelemenコントローラインスタンスに一致するフィールドにfx:id
  5. レジスタイベントハンドラ
  6. (そのようなメソッドが定義されている場合)、コントローラインスタンスでinitalize()を呼び出し
  7. とTSはFXML階層
  8. のルートに対応するUI要素を返します

load()の完了後(すなわち、 の後に@FXML - 注釈付きフィールドが注入されている)loader.getController()でコントローラへの参照を取得できますか。だからコントローラのファクトリ実装では非常に珍しいこととは別に、@FXML-injectedフィールドが初期化されるまでコントローラインスタンス上のメソッドを呼び出すことはできません。ここでのヌルチェックは冗長です。一方


あなたがfx:controllerを使用してはいけません、その場合、あなたのコントローラを、初期化するためにFXMLLoader.setController(...)を使用している場合、あなたは、コンストラクタに値を渡すことができます。

class Controller{ 
    @FXML 
    Pane aPane; 
    int globalValue; 

    public Controller(int globalValue) { 
     this.globalValue = globalValue ; 
    } 

    public Controller() { 
     this(0); 
    } 

    public void setSomething(int value){ 
     globalValue = value; 
     aPane.someMethod(globalValue) 
    } 

    @FXML 
    void initialize(){ 
     aPane.someMethod(globalValue) //guaranteed not null at this point 
    } 


} 

FXMLLoader loader = new FXMLLoader(getClass().getResource("path/to/fxml")); 
Controller controller = new Controller(42); 
loader.setController(controller); 
Node root = loader.load(); 
関連する問題