I am struggling to learn nested controllers in Java FX. I've read through some tutorials (most notably this one: https://www.youtube.com/watch?v=osIRfgHTfyg) and everything in my code looks okay... except my OuterController doesn't seem to have a reference to the InnerController.
To explain: I have an OuterController.java which controls the outer skeleton of my app. To keep this post brief, OuterController has a TabPane; the code of InnerController is meant to be the content of Tab1. (I've omitted the TabPane controller code for brevity.) "Tab1" has a single Button called "testMe".
Here's the Outer Controller. I'm certain the problem is in the "private @FXML InnerController myInnerController
" line. When the code runs, the "myInnerController
" variable is null:
// OuterController.java
package controllers;
import javafx.fxml.FXML;
public class OuterController{
private @FXML InnerController myInnerController; // << doesn't pick up the InnerController
Stage stage;
public void start(Stage stage) throws Exception{
this.stage = stage;
if(myInnerController == null){
System.out.println("Gack! InnerController is null!");
}
}
}
Here's the FXML for OuterController:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control....lots of import statements here....?>
<AnchorPane fx:id="AnchorPaneRoot" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="781.0" prefWidth="1356.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controllers.OuterController">
<children>
<TabPane fx:id="myTabPane" layoutX="14.0" layoutY="457.0" prefHeight="314.0" prefWidth="739.0" tabClosingPolicy="UNAVAILABLE">
<tabs>
<Tab text="Tab1">
<content>
<!-- include statement ties me to the InnerController -->
<fx:include fx:id="AnchorPaneInnerController" source="InnerController.fxml" />
</content></Tab>
</tabs>
</TabPane>
</children>
</AnchorPane>
Here's the Inner Controller:
// InnerController.java
package controllers;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
public class InnerController {
@FXML AnchorPane AnchorPaneInnerController; // not sure I need this
@FXML Button testMe;
private @FXML void initialize(){
System.out.println("Inner Controller started...!");
testMe.setOnAction(event -> {
System.out.println("testMe pressed!!!");
});
}
}
And for the sake of being complete, here's the FXML for the Inner Controller:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane fx:id="AnchorPaneInnerController" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="246.0" prefWidth="740.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controllers.InnerController.java">
<children>
<Button fx:id="testMe" layoutX="211.0" layoutY="108.0" mnemonicParsing="false" text="Test Me" />
</children>
</AnchorPane>
The code compiles and runs; there are no error codes or warnings. This is the output, assuming you click "testMe" three times:
Inner Controller started...!
Gack! InnerController is null!
testMe pressed!!!
testMe pressed!!!
testMe pressed!!!
You see the problem. InnerController runs just fine, and as a user I can click "testMe" to my heart's content. But why doesn't the OuterController's "myInnerController
" variable "point to" the instantiation of the InnerController? Is this a strict naming convention thing?
Another question... I tend to think of the "@FXML thingee variableName
" statement as an instruction to the Java controller file to mean "Look in your FXML file, you'll see an object of type 'thingee' with name 'variableName'; just load that as an instantiated object." If that's the case, then my "private @FXML InnerController myInnerController;
" may be tripping up because the variables names "myInnerController
" and "AnchorPaneInnerController
" from the InnerController FXML don't match...? Not sure what else could be the problem here.
Any advice and/or criticism is wildly appreciated, thank you.