Example below causes
javafx.fxml.LoadException: Root value already specified.
The code is written according to example here: http://docs.oracle.com/javafx/2/fxml_get_started/custom_control.htm
Code:
public class NavigationView extends ButtonBar {
private static final String defaultTemplate = "/fxml/navigator.fxml";
public NavigationView() {
this(null);
}
public NavigationView(URL resource) {
//FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("custom_control.fxml"));
if( resource == null ) {
resource = getClass().getResource(defaultTemplate);
}
FXMLLoader fxmlLoader = new FXMLLoader(resource);
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
}
public static class Runner extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
Scene scene = new Scene(new NavigationView(), 800, 600);
primaryStage.setTitle("NavigationView");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
Runner.launch(args);
}
}
}
If I remove line
fxmlLoader.setRoot(this);
then the view is empty, which is essential, because remains no connection between NavigationView
and FXML template.
How to accomplish?
UPDATE
FXML
is follows:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ButtonBar?>
<ButtonBar maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="38.0" prefWidth="651.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.91">
<buttons>
<Button fx:id="previousButton" mnemonicParsing="false" text="<< Previous" />
<Button fx:id="nextButton" mnemonicParsing="false" text="Next >>" />
<Button fx:id="editButton" mnemonicParsing="false" text="Edit" />
<Button fx:id="createButton" mnemonicParsing="false" text="Create" />
<Button fx:id="saveButton" mnemonicParsing="false" text="Save" />
<Button fx:id="cancelButton" mnemonicParsing="false" text="Cancel" />
<Button fx:id="deleteButton" mnemonicParsing="false" text="Delete" />
</buttons>
</ButtonBar>
Use a "dynamic root". The
<ButtonBar>
element is an instruction to theFXMLLoader
to create an object from theButtonBar
class, and (since it's the root element of the FMXL file) use it as the root of the structure created. If you want to callsetRoot(this)
, you already have an object created that is going to play that role.So you should use: