Java 控制器类中FXML控制器的getter而不是lookup?
我正在Java 控制器类中FXML控制器的getter而不是lookup?,java,javafx,java-8,javafx-8,Java,Javafx,Java 8,Javafx 8,我正在start()中加载FXML,我想把它们放在主窗口中,比如说有一个边框窗格 FXMLLoader loader = new FXMLLoader(); loader.setLocation(Main.class.getResource("Resources/Game.fxml")); Parent root = loader.load(); GameController gameManagerController = load
start()
中加载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();
现在,在根目录中查找borderPane将返回null,即使我给了它一个id(不是fx:id)。所以我的问题是,是否可以在gameManagerController
中为borderPane编写一个getter,然后执行类似的操作
gameManagerController.getBorderPane().setTop(topMenuBar);
在控制器之外公开UI元素通常不是一个好主意。这样做会使以后更改UI的组织方式变得更加困难,因为可能会有控制器FXML对之外的代码,这取决于特定的布局或存在的特定UI元素类
一个简单但更健壮的解决方案是定义一种方法,用于在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);
}
// ...
}
然后
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中发生的事情不太清楚。从控制器中公开UI元素通常不是一个好主意(尽管可能比使用非常脆弱的查找更好)。至少,在GameController
中定义一个方法来显示菜单,这样您就可以调用gameManagerController.showMenu(topMenuBar)
(根据需要命名方法)。你也可以考虑使用一个“视图模型”,但是在这种情况下它可能是多余的。<代码>显示菜单()/<代码>会做什么?它会这样做:BorderPane.setTop(topMenuBar)代码>@James_DI会在控制器中用一个更合适的字段名替换BorderPane
,但这是个好主意。关键是,如果您决定更改布局的管理方式,则所有更改仅限于控制器和FXML,您不需要更改超出此范围的代码。使用您建议的解决方案,如果以后需要,维护或更改您的UI会变得更加困难。当然,我对所有内容都使用有意义的名称。我明白了,再次谢谢你@James_DIs'ApplicationViewState'外观模式?否;不是真的。它实际上只是MVC中的一个模型。
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);