我认为你需要使用controllerFactory
在加载器中实现你想要的。当您使用controllerFactory
,您在 FXML 文件中指定控制器的类名,但控制器工厂允许您控制如何将其映射到对象(因此您仍然可以通过模型等来构造它)。当您指定一个controllerFactory
for an FXMLLoader
,该工厂还用于为任何<fx:include>
FXML 文件中的内容。
最后,请注意,您可以将所包含的 fxml 文件的控制器注入到“主”fxml 文件中,如FXML 文档的“嵌套控制器”部分.
因此,如果 startpage.fxml 如下所示:
<!-- imports etc -->
<BorderPane fx:controller="com.example.Startpage" ... >
<top>
<fx:include source="Menubar.fxml" fx:id="menubar" />
</top>
<!-- etc ... -->
</BorderPane>
和 Menubar.fxml 看起来像
<!-- imports etc -->
<MenuBar fx:controller="com.example.MenubarController" ... >
<!-- etc... -->
</MenuBar>
然后您可以通过以下方式控制控制器类的实例化:
FXMLLoader loader = new FXMLLoader(getClass().getResource("../fxml/startpage.fxml"));
Model m = ... ;
Startpage startpageController = new Startpage(m);
MenubarController menubarController = new MenubarController(m);
Callback<Class<?>, Object> controllerFactory = type -> {
if (type == Startpage.class) {
return startpageController ;
} else if (type == MenubarController.class) {
return menubarController ;
} else {
// default behavior for controllerFactory:
try {
return type.newInstance();
} catch (Exception exc) {
exc.printStackTrace();
throw new RuntimeException(exc); // fatal, just bail...
}
}
};
loader.setControllerFactory(controllerFactory);
Pane mainPane = loader.load();
现在,如果需要,您实际上可以在应用程序代码中引用两个控制器,但您也可以这样做
public class Startpage {
public final Model m ;
// note the name of this field must be xController,
// where x is the fx:id set on the <fx:include>:
@FXML
private final MenubarController menubarController ;
public Startpage(Model m) {
this.m = m ;
}
// ...
}
所以主控制器现在有了对菜单栏控制器的引用。