While trying to load an FXML file, one usually does something like the following:
FXMLLoader loader = FXMLLoader.load(getClass().getResource("File.fxml"));
Region root = loader.load();
Stage stage = new Stage();
stage.setScene(new Scene(root));
stage.show();
However, as I tried to put the loading code into the controller for "caller convenience" I did the following:
public Controller()
{
FXMLLoader loader = new FXMLLoader(getClass().getResource(fxml));
loader.setController(this);
Parent root = loader.load();
Stage stage = new Stage();
stage.setScene(new Scene(root));
stage.show();
}
This worked quite good, because now I just had to call the constructor to create the new window.
But I had to remove the
fx:controller="package.Class"
attribute in the FXML file, because otherwise an Exception ("javafx.fxml.LoadException: controller is already set") was thrown when I invoked the
fxmlloader.setController(this);
method in the constructor. Since I'm using NetBeans and its "Make Controller" feature (right-click on the FXML file), the controller class can't be created because of the missing attribute.
Summary:
What I want to achieve is a way to have the "fx:controller" attribute still set in the FXML (for NetBeans) and also being able to load the FXML conveniently inside the Controller class.
Is this possible, or do I need some kind of wrapper class which does create the FXML window(s)?
Thanks in advance.
You can do this:
public Controller()
{
FXMLLoader loader = new FXMLLoader(getClass().getResource(fxml));
loader.setControllerFactory(type -> {
if (type == Controller.class) {
return this ;
} else {
try {
return type.newInstance();
} catch (RuntimeException e) {
throw e ;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
Parent root = loader.load();
Stage stage = new Stage();
stage.setScene(new Scene(root));
stage.show();
}
which will allow you to (in fact, you will need to) have the fx:controller
attribute in the FXML file. Basically what this does is specifies a function that the FXMLLoader
can use to get the controller instance from the specified class. In this case, if the FXML Loader is looking for an object of the Controller
class, it returns the current object, otherwise just creates a new object of the specified class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With