我正在start()
中加载fxmls,我想将它们放在主窗口中,它说的是borderPane。
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返回null,即使我确实给它一个id(不是fx:id)。所以我的问题是,可以接受为gameManagerController
中的borderPane写一个getter而不是做这样的事情吗?
gameManagerController.getBorderPane().setTop(topMenuBar);
答案 0 :(得分:2)
在控制器之外公开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中发生的不同事情。