Warning: Declaration of Bootstrap_Walker_Nav_Menu::start_lvl(&$output, $depth) should be compatible with Walker_Nav_Menu::start_lvl(&$output, $depth = 0, $args = Array) in /homepages/10/d412081534/htdocs/clickandbuilds/WordPress/wordpress/wp-content/themes/stanleywp/functions/function-extras.php on line 61
Fxml | buildpath.de

FXML composition – how to get the controller of an included FXML?

The possibility to declare the UI with an FXML in JavaFX is pretty cool. In bigger applications you have to split the views in different FXMLs which allows you to reuse and compose them in complex FXMLs. Therefore you have to use the  <fx:include>  statement.

The include enables you to get the reference of the embedded view element in your FXML-controller class. Be sure that you use the value of fx:id as the name of the member in the controller class. The FXMLLoader will pass the reference once the View was created.

[...]
<fx:include fx:id="embeddedView" source="SomeOtherView.fxml"/>
[...]
class AViewController{
    @FXML
    Parent embeddedView; //fx:id value as Variable name -> JavaFX injects the reference of the root element in the included FXML
}

Ok, we have the reference of the view element, but how can we get the reference of the embeddedView’s controller?  The solution is a naming convention which you can find here.


Short example (GitHub)

First Step: Create the FXML and the Java Controller which we want to embed:

 <AnchorPane xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="de.saxsys.fxml.RedView">
 <children>
 <Pane prefHeight="200.0" prefWidth="200.0">
 <children>
 <Button fx:id="button1" layoutX="68.0" layoutY="50.0" mnemonicParsing="false" text="Button" />
 <Button fx:id="button2" layoutX="68.0" layoutY="121.0" mnemonicParsing="false" text="Button" />
 </children>
 </Pane>
 </children>
</AnchorPane>
public class RedView {

    @FXML
    private Button button2;

    @FXML
    private Button button1;

    public void foo(String foo) {
       System.out.println(foo);
    }
}
redview

RedView.fxml

Second Step: Create the View which should embed the RedView.fxml. It’s not problem to do this using the Scene Builder. If you are using the developer preview of the Scene Builder 2, you may have problems to set an fx:id to the included elements – in this case add the fx:id attribute directly in the fxml code.

Add

Include FXML files using the SceneBuilder – Don’t forget to set the fx:id to the included element

 <VBox xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.saxsys.fxml.MainView">
 <children>
 <!--Some element -->
 <Circle radius="100.0" stroke="BLACK" strokeType="INSIDE" />
 <!--our included FXML -->
 <fx:include fx:id="embeddedRedView" source="RedView.fxml" />
 <!--Some other element -->
 <Circle radius="100.0" stroke="BLACK" strokeType="INSIDE" />
 </children>
</VBox>
public class MainView {

	@FXML
	private Parent embeddedRedView; //embeddedElement

	@FXML
	private RedView embeddedRedViewController; // $embeddedElement+Controller

	public void initialize() {
		System.out.println(embeddedRedViewController);
		System.out.println(embeddedRedView);
                embeddedRedViewController.foo("It works"); //Console print "It works"
	}
}
Added

Embedded RedView.fxml into MainView.fxml using the Scene Builder

As you can see, we can get the reference of the nested controller by appending the word Controller in addition to the variable name of the embedded element.

public class Starter extends Application {

	@Override
	public void start(Stage stage) throws Exception {

		Parent parent = FXMLLoader.load(getClass().getResource("MainView.fxml"));
		Scene scene = new Scene(parent);
		stage.setScene(scene);
		stage.show();
	}

	public static void main(String[] args) {
		launch(args);
	}

}

Let’s try it – create an JavaFX application which loads the MainView.fxml and you’ll see the printed message on the console, which prooves that we accessed the reference to the FXML-controller of the embedded FXML element.

Example on GitHub