Subcontroller not being injected into main control

2019-02-16 22:35发布

问题:

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!

回答1:

To use @FXML tag you have to provide fx:id.

Update your main.fxml:

<bottom>
    <fx:include fx:id="statusbar" source="statusbar.fxml" />
</bottom>

After that you can use next constants in your MainController.java:

@FXML
Label statusbar; // node itself
@FXML
private StatusBarController statusbarController; // controller

Note, that statusbarControlleris not a partialy lowercased class name, but fx:id + Controller word.



回答2:

There seems to be a bug in netbeans 8.0 with nested fxmls as well. Cannot count on netbeans to create the nested fxml's controller object for you, it has to be manually inserted into your MainController. Every time the controller is updated in netbeans it gets wiped out so it can be kind of tedious. For this example that would be inserting the

@FXML private StatusBarController statusbarController;

line manually into the main controller in this case, then it works normally. Very useful for organizing large fxmls/controllers.