在控制器之外公開UI元素通常不是好主意。這樣做會使得以後更改組織UI的方式變得更加困難,因爲您可能擁有取決於特定佈局或特定UI元素類的controller-FXML對之外的代碼。
一個簡單的,但更強大的解決方案,只是在GameController
定義一個方法用於顯示菜單的目的:
public class GameController {
@FXML
private BorderPane rootPane ;
// ...
public void showMenu(Node menu) {
rootPane.setTop(menu);
}
// ...
}
,現在你可以做
gameManagerController.showMenu(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);
}
// ...
}
現在你可以共享控制器之間的視圖模型,可以觀察和更新狀態,因爲它們需要的單一實例:
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);
的這種方法的優勢在於它爲任何控制器提供了一種機制,可以在應用程序的其他部分更新UI,而無需「瞭解」其他控制器。這有助於解耦用戶界面的各個部分。缺點是增加了應用程序的複雜性 - 可能很難調試,因爲不太清楚在UI中發生的不同事情。
從控制器中公開UI元素通常不是一個好主意(儘管它可能比使用查找非常脆弱)。至少,在'GameController'中定義一個顯示菜單的方法,這樣你就可以調用'gameManagerController.showMenu(topMenuBar)'(爲任何適當的方法命名)。你也可以考慮使用「視圖模型」,但在這種情況下它可能是矯枉過正的。 –
'showMenu()'會做什麼?它會這樣做:'BorderPane.setTop(topMenuBar);'? @James_D – shinzou
我會在控制器中用一個更合適的字段名替換'BorderPane',但是,是的,這是想法。重點是,如果您決定更改佈局的管理方式,所有更改僅限於控制器和FXML,您不需要更改代碼。如果您以後需要使用您的建議解決方案,維護或更改您的用戶界面將變得更加困難。 –