4 Replies Latest reply: Feb 11, 2013 12:46 PM by 990159 RSS

    Subcontroller not being injected into main controller

    990159
      I have a BorderPane (associated with a MainController), the FXML for the BorderPane uses <fx:include> to include a Label (with a controller StatusBarController) into the bottom region of the BorderPane. Unfortunately the the StatusBarController is not injected into the MainController class instance and I can't understand why.

      main.fxml: BorderPane with the included statusbar
      <fx:root type="javafx.scene.layout.BorderPane" fx:id="borderPane" xmlns:fx="http://javafx.com/fxml" fx:controller="com.example.controllers.MainController">
        <bottom>
          <fx:include source="statusbar.fxml" />
        </bottom>
      </fx:root>
      statusbar.fxml: The Label and it's associated controller
      <Label fx:id="statusbar" text="A label simulating a status bar" xmlns:fx="http://javafx.com/fxml" fx:controller="com.example.controllers.StatusBarController" />
      The MainController with a field for the StatusBarController:
      public class MainController
      {
          @FXML
          private StatusBarController statusbarController; // PROBLEM HERE: I would expect the StatusBarController to be injected but this does not happen!
      
          
          // Implementing Initializable Interface no longer required on JavaFX 2.2 according to
          // http://docs.oracle.com/javafx/2/fxml_get_started/whats_new2.htm
          // (I also tested this, the initialize() method is being called)
          @SuppressWarnings("unused") // only called by the FXMLLoader
          @FXML // This method is called by the FXMLLoader when initialization is complete
          private void initialize() {
              // initialize your logic here: all @FXML variables will have been injected
               assert borderPane != null : "fx:id=\"borderPane\" was not injected: check your FXML file 'main.fxml'.";
              System.out.println("MainController initialize()");
      
              //statusbarController.setStatusText("Hello from MainController"); // PROBLEM HERE: this fails because statusbarController is not injected as expected
          }
      }
      And the start of the application:
           public void start(Stage primaryStage) 
           {          
                Parent root = null;
                
                try {
                     root = FXMLLoader.load(getClass().getResource("/resources/main.fxml"));
                } catch (IOException e) {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
                }
      
                primaryStage.setTitle("Demo");
                primaryStage.setScene(new Scene(root, 800, 600));
                primaryStage.show();
           }
      The full source code of my sample is available at http://codestefan.googlecode.com/svn/trunk/SubcontrollerAccess/
      So the question is: Why is the StatusBarController not injected into the statusbarController variable of the MainController? Thanks for any hint!

      Edited by: 987156 on 09.02.2013 11:07
        • 1. Re: Subcontroller not being injected into main controller
          jsmith
          Just guessing but probably the sub controller needs the fx:root syntax like it's parent.

          Edited by: jsmith on Feb 9, 2013 9:20 PM

          After reading the fxml documentation it would seem that an fx:root specifier is not necessary in the included fxml. As James points out, fx:id is required if you want to inject the included controller into the main controller.

          Relevant documentation references are fx:include
          http://docs.oracle.com/javafx/2/api/javafx/fxml/doc-files/introduction_to_fxml.html#include_elements

          And also Nested Controllers:
          http://docs.oracle.com/javafx/2/api/javafx/fxml/doc-files/introduction_to_fxml.html#nested_controllers
          • 2. Re: Subcontroller not being injected into main controller
            James_D
            When I've used nested controllers, I've always put the fx:id on the fx:include tag:

            main.fxml
            <fx:root type="javafx.scene.layout.BorderPane" fx:id="borderPane" xmlns:fx="http://javafx.com/fxml" fx:controller="com.example.controllers.MainController">
              <bottom>
                <fx:include source="statusbar.fxml"  fx:id="statusbar" />
              </bottom>
            </fx:root>
            and then statusbar.fxml would just be
            <Label text="A label simulating a status bar" xmlns:fx="http://javafx.com/fxml" fx:controller="com.example.controllers.StatusBarController" />
            • 3. Re: Subcontroller not being injected into main controller
              bouye
              Yeah, the main issue here is probably the lack of fx:id on the fx:include bit.
              • 4. Re: Subcontroller not being injected into main controller
                990159
                Thank you all very much, yes, it was the fx:id missing directly on the fx:include! Obviously this also makes sense to decouple a general FXML code from a concrete ID :-)