This discussion is archived
4 Replies Latest reply: Feb 11, 2013 10:46 AM by 990159 RSS

Subcontroller not being injected into main controller

990159 Newbie
Currently Being Moderated
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 Guru
    Currently Being Moderated
    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 Guru
    Currently Being Moderated
    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 Journeyer
    Currently Being Moderated
    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 Newbie
    Currently Being Moderated
    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 :-)

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points