I think you need to use a controllerFactory
in the loader to achieve what you want here. When you use a controllerFactory
, you specify the classname of the controller in the FXML files, but the controller factory allows you to control how that is mapped to an object (so you can still construct it passing in a model, etc). When you specify a controllerFactory
for an FXMLLoader
, that factory is also used to create the controllers for any <fx:include>
s that you have in the FXML file.
Finally, note that you can inject the controller for the included fxml file into the "main" fxml file, as documented in the "Nested controllers" section of the FXML documentation.
So if startpage.fxml looks like this:
<!-- imports etc -->
<BorderPane fx:controller="com.example.Startpage" ... >
<top>
<fx:include source="Menubar.fxml" fx:id="menubar" />
</top>
<!-- etc ... -->
</BorderPane>
and Menubar.fxml looks like
<!-- imports etc -->
<MenuBar fx:controller="com.example.MenubarController" ... >
<!-- etc... -->
</MenuBar>
Then you can control the instantiation of the controller classes with:
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();
Now you actually have references to both controllers in your application code, if you need, but you can also do
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 ;
}
// ...
}
So the main controller now has a reference to the menu bar controller.