2016-09-05 2 views
1

start()にfxmlsをロードしていて、borderPaneというメインウィンドウに配置したいと思います。ルックアップの代わりにコントローラクラスのFXMLコントローラのゲッター?

 FXMLLoader loader = new FXMLLoader(); 
     loader.setLocation(Main.class.getResource("Resources/Game.fxml")); 
     Parent root = loader.load(); 
     GameController gameManagerController = loader.getController(); 

     loader = new FXMLLoader(); 
     loader.setLocation(getClass().getResource("Resources/TopMenuBar.fxml")); 
     Parent topMenuBar = loader.load(); 
     TopMenuBarController topMenuBarController = loader.getController(); 

rootでborderPaneのルックアップは、私はそれをID(:IDないFX)を得なかったにも関わらず、nullを返しています。だから私の質問は、代わりにgameManagerControllerのborderPaneのゲッターを書くことが許容され、代わりにこのような何か?

gameManagerController.getBorderPane().setTop(topMenuBar); 
+1

コントローラからUI要素を公開することは、通常はお勧めできません(ただし、ルックアップを使用するよりもはるかに壊れやすくなります)。最低限、 'GameController'にメソッドを定義してメニューを表示してください。' gameManagerController.showMenu(topMenuBar) 'を呼び出すことができます。また、「ビューモデル」の使用を検討することもできますが、この状況ではおそらく過剰です。 –

+0

'showMenu()'は何をしますか?これを行うかどうか: 'BorderPane.setTop(topMenuBar);'? @ James_D – shinzou

+2

私は 'BorderPane'をコントローラーのより適切なフィールド名に置き換えますが、それは考え方です。要点は、レイアウトの管理方法を変更する場合、すべての変更がコントローラとFXMLに制限されているため、その外のコードを変更する必要はありません。提案されたソリューションを使用すると、後で行う必要がある場合は、UIを維持または変更することが非常に困難になります。 –

答えて

2

通常、コントローラの外にUI要素を公開することはお勧めできません。そうすることで、後でUIをどのように構成するかを変更するのがずっと難しくなります。特定のレイアウトや特定のUI要素クラスに依存するコントローラ-FXMLペアの外側にコードが存在する可能性があります。

シンプルですが、より堅牢なソリューション、ちょうどGameControllerでメニューを表示する目的のための方法を定義することです:

public class GameController { 

    @FXML 
    private BorderPane rootPane ; 

    // ... 

    public void showMenu(Node menu) { 
     rootPane.setTop(menu); 
    } 

    // ... 
} 

、今、あなたは

gameManagerController.showMenu(topMenuBar); 

を行うことができますこのような状況では過度に複雑すぎるかもしれませんが、見た目にも価値のある、より複雑なアプローチは、アプリケーションのビューステートを表すために「ビューモデル」を使用することです。

public class GameController { 

    @FXML 
    private BorderPane rootPane ; 

    private ApplicationViewState viewState ; 

    public void setViewState(ApplicationViewState viewState) { 
     this.viewState = viewState ; 
     rootPane.topProperty().bind(viewState.menuProperty()); 
    } 

    // ... 
} 

をしてから

FXMLLoader loader = new FXMLLoader(); 
loader.setLocation(Main.class.getResource("Resources/Game.fxml")); 
Parent root = loader.load(); 
GameController gameManagerController = loader.getController(); 

loader = new FXMLLoader(); 
loader.setLocation(getClass().getResource("Resources/TopMenuBar.fxml")); 
Parent topMenuBar = loader.load(); 
TopMenuBarController topMenuBarController = loader.getController(); 


ApplicationViewState viewState = new ApplicationViewState(); 
gameManagerController.setViewState(viewState); 
viewState.setMenu(topMenuBar); 

:今、あなたは彼らが必要とするような状態を観察し、更新することができ、コントローラ、間のビューモデルの単一のインスタンスを共有することができ

public class ApplicationViewState { 

    private final ObjectProperty<Node> menu = new SimpleObjectProperty<>(); 
    private final ObjectProperty<Node> content = new SimpleObjectProperty<>(); 

    public ObjectProperty<Node> menuProperty() { 
     return menu ; 
    } 

    public final Node getMenu() { 
     return menuProperty().get(); 
    } 

    public final void setMenu(Node menu) { 
     menuProperty().set(menu); 
    } 


    public ObjectProperty<Node> contentProperty() { 
     return content ; 
    } 

    public final Node getContent() { 
     return contentProperty().get(); 
    } 

    public final void setContent(Node content) { 
     contentProperty().set(content); 
    } 

    // ... 
} 

このアプローチの利点は、他のコントローラを「知る」ことなく、コントローラがアプリケーションの他の部分でUIを更新するためのメカニズムを提供することです。これは、UIのさまざまな部分をデカップリングするのに役立ちます。欠点は、アプリケーションの複雑さが増していることです。UIでさまざまなことがどのように起こっているのかがはっきりしないため、デバッグするのが難しい場合があります。

+0

'ApplicationViewState'はファサードパターンですか? – shinzou

+0

いいえ。あんまり。これはMVCの単なるモデルです。 –

関連する問題