1

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="&lt;&lt; Previous" />
      <Button fx:id="nextButton" mnemonicParsing="false" text="Next &gt;&gt;" />
      <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>
Dims
  • 47,675
  • 117
  • 331
  • 600

1 Answers1

3

Use a "dynamic root". The <ButtonBar> element is an instruction to the FXMLLoader to create an object from the ButtonBar 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 call setRoot(this), you already have an object created that is going to play that role.

So you should use:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ButtonBar?>

<fx:root type="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="&lt;&lt; Previous" />
      <Button fx:id="nextButton" mnemonicParsing="false" text="Next &gt;&gt;" />
      <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>
</fx:root>
James_D
  • 201,275
  • 16
  • 291
  • 322
  • But what if I wish to use ``? I found workaround by creating extra container outside FXML. Are there any other ways? – Dims May 03 '16 at 08:56
  • This does create a button bar, because the object you are setting as root is a ButtonBar instance: NavigationView extends ButtonBar. – James_D May 03 '16 at 09:40
  • I guess the question is, if you use `` *and* create a subclass of `ButtonBar`, you have two button bars. Why do you want two of them? – James_D May 03 '16 at 09:45