package de.saring.util.gui.javafx; import java.io.IOException; import java.net.URL; import java.util.Objects; import java.util.ResourceBundle; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; /** * Util class with helper methods for loading FXML layouts. * * @author Stefan Saring */ public final class FxmlLoader { private FxmlLoader() { } /** * Loads the scene object hierarchy from the specified FXML document. This is a wrapper * for the {@link FXMLLoader#load(URL, ResourceBundle)} method. It uses the passed controller * instead of creating a new controller class specified in the FXML file. The passed controller * needs to be an instance of the same class. * * @param url URL of the FXML resource * @param resBundle the ResourceBundle to use for the FXML document * @param controller controller to be used for the loaded hierarchy * * @return the loaded scene object hierarchy * @throws IOException */ public static Parent load(final URL url, final ResourceBundle resBundle, final Object controller) throws IOException { Objects.requireNonNull(url); Objects.requireNonNull(controller); final FXMLLoader loader = new FXMLLoader(); loader.setLocation(url); loader.setResources(resBundle); // setController() can't be used here, because the controller class is already specified in FXML // (declaration in FXML is very helpful for validation and event handler selection in SceneBuilder) loader.setControllerFactory(controllerClass -> { if (controllerClass != null && !controllerClass.isInstance(controller)) { throw new IllegalArgumentException("Invalid controller instance, expecting instance of class '" + controllerClass.getName() + "'!"); } return controller; }); return (Parent) loader.load(); } }