在控制器之外公开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,您不需要更改代码。如果您以后需要使用您的建议解决方案,维护或更改您的用户界面将变得更加困难。 –