Code-behind class

You can combine an FXML markup file with a Java source code file (called a code-behind class), allowing you to combine declarative markup and imperative code. Simply create two files in the same package:

  • com/sample/MyControl.fxml
  • com/sample/MyControl.java

In MyControl.fxml, add the fx:class attribute to the root element, and specify the fully-qualified name of the code-behind class.

com/sample/MyControl.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.control.Button?>

<StackPane xmlns="http://javafx.com/javafx" xmlns:fx="http://jfxcore.org/fxml/2.0"
           fx:class="com.sample.MyControl">
    <Button fx:id="myButton1"/>
</StackPane>

In MyControl.java, create a new class that extends MyControlBase.

com/sample/MyControl.java
package com.sample;

public class MyControl extends MyControlBase {
    public MyControl() {
        initializeComponent();
        myButton1.setText("Hello!");
    }
}

The MyControlBase class is generated by the FXML compiler; it contains the compiled markup of the FXML file. If the MyControlBase class is missing, run the :processFxml task in your Gradle build to create the class.

By default, the name of the generated markup class corresponds to the name of the FXML file with the Base suffix. This can be changed with the fx:markupClassName attribute.

Initializing the scene graph with initializeComponent

The scene graph specified in the FXML file is initialized by the compiler-generated initializeComponent() method. It is important that you call this method in the constructor of the code-behind class, as otherwise the components that make up the FXML file will never be instantiated.

You should call initializeComponent() after you initialize all of the state which the FXML scene graph depends on, but before you actually access the FXML scene graph.

What is the relationship between fx:class, fx:controller, and fx:root?

fx:controller and fx:root are both directives of the FXML 1.0 format, and are not available in the FXML 2.0 format. fx:class is a new directive that allows combining markup and imperative code. This is similar to the fx:root directive, but doesn’t require using FXMLLoader to load the markup at runtime.

FXML 2.0 always compiles down to scene graph nodes; it does not support the markup/controller model of FXML 1.0 out of the box. Instead, it is left to developers to implement their favorite architectural patterns. FXML 2.0 is well-suited to implement patterns like MVC or MVVM.