FXML

JavaFX FXML Controller Example

Photo of Andreas PomarolliAndreas PomarolliApril 7th, 2016Last Updated: April 24th, 2019
1 6,431 11 minutes read

This is a JavaFX FXML Controller Example. FXML is an XML-based language designed to build the user interface for JavaFX applications. You can use FXML to build an entireScene or part of aScene. FXML allows application developers to separate the logic for building the UI from the business logic. If the UI part of the application changes, you do not need to recompile the JavaFX code. Instead you can change the FXML using a text editor and rerun the application. You still use JavaFX to write business logic using the Java language. An FXML document is an XML document.

A JavaFX scene graph is a hierarchical structure of Java objects. XML format is well suited for storing information representing some kind of hierarchy. Therefore, using FXML to store the scene-graph is very intuitive. It is common to use FXML to build a scene graph in a JavaFX application.

 
The following table shows an overview of the whole article:

The following examples uses Java SE 7 and JavaFX 2.2.

1. Introduction to FXML

1.1 The FXML Code

FxFXMLExample1.fxml

<?xml version="1.0" encoding="UTF-8"?><?language JavaScript?><?import javafx.scene.control.*?><?import javafx.scene.layout.*?><VBox fx:id="vbox" layoutX="10.0" layoutY="10.0" prefHeight="250.0" prefWidth="300.0" spacing="10" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2">  <style>-fx-padding: 10;-fx-border-style: solid inside;-fx-border-width: 2;-fx-border-insets: 5;-fx-border-radius: 5;-fx-border-color: blue;  </style>  <children>    <Label fx:id="inputLbl" alignment="CENTER_LEFT" cache="true" cacheHint="SCALE" prefHeight="30.0" prefWidth="200.0" text="Please insert Your Input here:" textAlignment="LEFT" />    <TextField fx:id="inputText" prefWidth="100.0" />    <Button fx:id="okBtn" alignment="CENTER_RIGHT" contentDisplay="CENTER" mnemonicParsing="false" text="OK" textAlignment="CENTER" />    <Label fx:id="outputLbl" alignment="CENTER_LEFT" cache="true" cacheHint="SCALE" prefHeight="30.0" prefWidth="200.0" text="Your Input:" textAlignment="LEFT" />    <TextArea fx:id="outputText" prefHeight="100.0" prefWidth="200.0" wrapText="true" />  </children></VBox>

1.2 Adding UI Elements

The root element of the FXML document is the top-level object in the object-graph. The top-level object of the above example is aVBox. Therefore, the root element of your FXML would be:

<VBox></VBox>

How do you know that to represent aVBox in the object-graph, you need to use a tag in FXML? It is both difficult and easy. It is difficult because there is no documentation for FXML tags. It is easy because FXML has a few rules explaining what constitutes a tag name. For example, if a tag name is the simple or fullqualified name of a class, the tag will create an object of that class. The above element will create an object of theVBox class. The above FXML can be rewritten using the fully qualified class name:

<javafx.scene.layout.VBox></javafx.scene.layout.VBox>

In JavaFX, layout panes have children. In FXML, layout panes have children as their child elements. You can add aLabel and aButton and other elements to theVBox as follows:

<children><Label/><TextField/><Button/><Label/><TextArea/></children>

This defines the basic structure of the object-graph for our application. It will create aVBox with two labels, aTextField, aTextArea and aButton.

1.3 Importing Java Types in FXML

To use the simple names of Java classes in FXML, you must import the classes as you do in Java programs. There is one exception. In Java programs, you do not need to import classes from thejava.lang package. However, in FXML, you need to import classes from all packages, including thejava.lang package. An import processing instruction is used to import a class or all classes from a package. The following processing instructions import theVBox,Label, andButton classes:

<?import javafx.scene.layout.VBox?><?import javafx.scene.control.Label?><?import javafx.scene.control.Button?>

The following import processing instructions import all classes from thejavafx.scene.control andjava.lang packages:

<?import javafx.scene.control.*?><?import java.lang.*?>

1.4 Setting Properties in FXML

You can set properties for Java objects in FXML. A property for an object can be set in FXML if the property declaration follows the JavaBean conventions. The attribute name or the property element name is the same as the name of the property being set. The following FXML creates aTextField and sets itsprefWidth property using an attribute:

<TextField fx:id="inputText" prefWidth="100.0" />

1.5 Specifying FXML Namespace

FXML does not have an XML schema. It uses a namespace that needs to be specified using the namespace prefix “fx”. For the most part, the FXML parser will figure out the tag names such as tag names that are classes, properties of the classes, and so on. FXML uses special elements and attribute names, which must be qualified with the “fx” namespace prefix. Optionally, you can append the version of the FXML in the namespace URI. The FXML parser will verify that it can parse the specified.

The following FXML declares the “fx” namespace prefix.

<VBox xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2">...</VBox>

1.6 Assigning an Identifier to an Object

An object created in FXML can be referred to somewhere else in the same document. It is common to get the reference of UI objects created in FXML inside the JavaFX code. You can achieve this by first identifying the objects in FXML with anfx:id attribute. The value of thefx:id attribute is the identifier for the object. If the object type has an id property, the value will be also set for the property. Note that eachNode in JavaFX has an id property that can be used to refer to them in CSS. The following is an example of specifying thefx:id attribute for aLabel.

<Label fx:id="inputLbl"/>

1.7 The Corresponding Java Class

FxFXMLExample1.java

import java.io.FileInputStream;import java.io.IOException;import javafx.application.Application;import javafx.fxml.FXMLLoader;import javafx.scene.Scene;import javafx.scene.layout.VBox;import javafx.stage.Stage;public class FxFXMLExample1 extends Application{public static void main(String[] args) {Application.launch(args);}@Overridepublic void start(Stage stage) throws IOException{// Create the FXMLLoader FXMLLoader loader = new FXMLLoader();// Path to the FXML FileString fxmlDocPath = "Path-To-Your-FXML-Files/FxFXMLExample1.fxml";FileInputStream fxmlStream = new FileInputStream(fxmlDocPath);// Create the Pane and all DetailsVBox root = (VBox) loader.load(fxmlStream);// Create the SceneScene scene = new Scene(root);// Set the Scene to the Stagestage.setScene(scene);// Set the Title to the Stagestage.setTitle("A simple FXML Example");// Display the Stagestage.show();}}

An FXML document defines the view part (the GUI) of a JavaFX application. You need to load the FXML document to get the object-graph it represents. Loading an FXML is performed by an instance of theFXMLLoader class. TheFXMLLoader class provides several constructors that let you specify the location, charset, resource bundle, and other elements to be used for loading the document.FXMLLoader supports loading a FXML document using anInputStream. The following snippet of code loads the same FXML document using anInputStream.

// Create the FXMLLoader FXMLLoader loader = new FXMLLoader();// Path to the FXML FileString fxmlDocPath = "Path-To-Your-FXML-Files/FxFXMLExample1.fxml";FileInputStream fxmlStream = new FileInputStream(fxmlDocPath);

Internally, theFXMLLoader reads the document using streams, which may throw anIOException. All versions of theload() method inFXMLLoader class throwIOException. In your application, you will need to handle the exception. TheFXMLLoader class contains several versions of theload() method. Some of them are instance methods and some static methods. You need to create anFXMLLoader instance and use the instanceload() method, if you want to retrieve more information from the loader, such as the controller reference, resource bundle, the location, charset, and root object.

// Create the Pane and all DetailsVBox root = (VBox) loader.load(fxmlStream);

What do you do next after loading an FXML document? The loader returns aVBox, which is set as the root for theScene. The rest of the code is the same as you have been using except for one difference in the declaration of thestart() method. The method declares that it may throw anIOException, which you had to add because you have called theload() method of theFXMLLoader inside the method.

// Create the SceneScene scene = new Scene(root);// Set the Scene to the Stagestage.setScene(scene);// Set the Title to the Stagestage.setTitle("A simple FXML Example");// Display the Stagestage.show();

1.8 The GUI

The following mage shows the application after starting. But at this time, a click on the OK-Button has no effect. The reason for this behaviour is the fact, that we have not defined anEventHandler at this time.

A simple JavaFX FXML Example
A simple JavaFX FXML Example

2. Using Script Event Handlers

2.1 The FXML Code

FxFXMLExample2.fxml

<?xml version="1.0" encoding="UTF-8"?><?language JavaScript?><?import javafx.scene.control.*?><?import javafx.scene.layout.*?><VBox fx:id="vbox" layoutX="10.0" layoutY="10.0" prefHeight="250.0" prefWidth="300.0" spacing="10" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2">  <style>-fx-padding: 10;-fx-border-style: solid inside;-fx-border-width: 2;-fx-border-insets: 5;-fx-border-radius: 5;-fx-border-color: blue;  </style>  <children>    <Label fx:id="inputLbl" alignment="CENTER_LEFT" cache="true" cacheHint="SCALE" prefHeight="30.0" prefWidth="200.0" text="Please insert Your Input here:" textAlignment="LEFT" />    <TextField fx:id="inputText" prefWidth="100.0" />    <Button fx:id="okBtn" alignment="CENTER_RIGHT" contentDisplay="CENTER" mnemonicParsing="false" onAction="printOutput();" text="OK" textAlignment="CENTER" />    <Label fx:id="outputLbl" alignment="CENTER_LEFT" cache="true" cacheHint="SCALE" prefHeight="30.0" prefWidth="200.0" text="Your Input:" textAlignment="LEFT" />    <TextArea fx:id="outputText" prefHeight="100.0" prefWidth="200.0" wrapText="true" />    <fx:script>function printOutput() {outputText.setText(inputText.getText());}</fx:script>      </children></VBox>

You can set event handlers for nodes in FXML. Setting an event handler is similar to setting any other properties. In FXML, you can specify two types of event handlers:

  • Script Event Handlers
  • Controller Event Handlers

In this chapter we will discuss Script Event Handlers. The Controller Event Handlers will be discussed in the following chapter.

The script event handler is used when the event handler is defined in a scripting language. The value of the attribute is the script itself, such as a function call or one or more statements. The following snippet of FXML sets theActionEvent handler for aButton that calls theprintOutput() function defined using JavaScript.

<?language JavaScript?><fx:script>function printOutput() {outputText.setText(inputText.getText());}</fx:script>

If you want to execute the functionprintOutput() when theButton is clicked, you can set the event handler as:

Want to master JavaFX ?
Subscribe to our newsletter and download theJavaFXProgramming Cookbookright now!
In order to get you prepared for your JavaFX development needs, we have compiled numerous recipes to help you kick-start your projects. Besides reading them online you may download the eBook in PDF format!

Thank you!

We will contact you soon.

<Button fx:id="okBtn" onAction="printOutput();" text="OK" textAlignment="CENTER" />

2.2 The Corresponding Java Class

FxFXMLExample2.java

import java.io.FileInputStream;import java.io.IOException;import javafx.application.Application;import javafx.fxml.FXMLLoader;import javafx.scene.Scene;import javafx.scene.layout.VBox;import javafx.stage.Stage;public class FxFXMLExample2 extends Application{public static void main(String[] args) {Application.launch(args);}@Overridepublic void start(Stage stage) throws IOException{// Create the FXMLLoader FXMLLoader loader = new FXMLLoader();// Path to the FXML FileString fxmlDocPath = "Path-To-Your-FXML-Files/FxFXMLExample2.fxml";FileInputStream fxmlStream = new FileInputStream(fxmlDocPath);// Create the Pane and all DetailsVBox root = (VBox) loader.load(fxmlStream);// Create the SceneScene scene = new Scene(root);// Set the Scene to the Stagestage.setScene(scene);// Set the Title to the Stagestage.setTitle("A FXML Example with a Script Event Handler");// Display the Stagestage.show();}}

2.3 The GUI

The following image shows the result of our program after inserting a Text in theTextField and pressing theButton “OK”:

A JavaFX FXML Example with a JavaScript Event Handler
A JavaFX FXML Example with a JavaScript Event Handler

3. Using Controller Event Handlers

3.1 The FXML Code

FxFXMLExample3.fxml

<?xml version="1.0" encoding="UTF-8"?><?import javafx.scene.control.*?><?import javafx.scene.layout.*?><VBox fx:id="vbox" layoutX="10.0" layoutY="10.0" prefHeight="250.0" prefWidth="300.0" spacing="10" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="FxFXMLController">  <style>-fx-padding: 10;-fx-border-style: solid inside;-fx-border-width: 2;-fx-border-insets: 5;-fx-border-radius: 5;-fx-border-color: blue;  </style>  <children>    <Label fx:id="inputLbl" alignment="CENTER_LEFT" cache="true" cacheHint="SCALE" prefHeight="30.0" prefWidth="200.0" text="Please insert Your Input here:" textAlignment="LEFT" />    <TextField fx:id="inputText" prefWidth="100.0" />    <Button fx:id="okBtn" alignment="CENTER_RIGHT" contentDisplay="CENTER" mnemonicParsing="false" onAction="#printOutput" text="OK" textAlignment="CENTER" />    <Label fx:id="outputLbl" alignment="CENTER_LEFT" cache="true" cacheHint="SCALE" prefHeight="30.0" prefWidth="200.0" text="Your Input:" textAlignment="LEFT" />    <TextArea fx:id="outputText" prefHeight="100.0" prefWidth="200.0" wrapText="true" />  </children></VBox>

A controller is simply a class name whose object is created by FXML and used to initialize the UI elements. FXML lets you specify a controller on the root element using thefx:controller attribute. Note that only one controller is allowed per FXML document, and if specified, it must be specified on the root element. The following FXML specifies a controller for theVBox element.

<VBox fx:id="vbox" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="FxFXMLController">

A controller needs to conform to some rules and it can be used for different reasons:

  • The controller is instantiated by the FXML loader.
  • The controller must have a public no-args constructor. If it does not exist, the FXML loader will not be able to instantiate it, which will throw an exception at the load time.
  • The controller can have accessible methods, which can be specified as event handlers in FXML.
  • The FXML loader will automatically look for accessible instance variables of the controller. If the name of an accessible instance variable matches the fx:id attribute of an element, the object reference from FXML is automatically copied into the controller instance variable. This feature makes the references of UI elements in FXML available to the controller. The controller can use them later, such as binding them to model.
  • The controller can have an accessible initialize() method, which should take no arguments and have a return type of void. The FXML loader will call the initialize() method after the loading of the FXML document is complete.

3.2 The Controller Class

FxFXMLController.java

import java.net.URL;import java.util.ResourceBundle;import javafx.fxml.FXML;import javafx.scene.control.TextArea;import javafx.scene.control.TextField;public class FxFXMLController {@FXML// The reference of inputText will be injected by the FXML loaderprivate TextField inputText;// The reference of outputText will be injected by the FXML loader@FXMLprivate TextArea outputText;// location and resources will be automatically injected by the FXML loader@FXMLprivate URL location;@FXMLprivate ResourceBundle resources;// Add a public no-args constructorpublic FxFXMLController() {}@FXMLprivate void initialize() {}@FXMLprivate void printOutput() {outputText.setText(inputText.getText());}}

The controller class uses a@FXML annotation on some members. The@FXML annotation can be used on fields and methods. It cannot be used on classes and constructors. By using a@FXML annotation on a member, you are declaring that the FXML loader can access the member even if it is private. A public member used by the FXML loader does not need to be annotated with@FXML. However, annotating a public member with@FXML is not an error. It is better to annotate all members, public and private, used by the FXML loader with the@FXML annotation. This tells the reader of your code how the members are being used.

The following FXML sets theprintOutput() method of the controller class as the event handler for theButton:

<VBox fx:id="vbox" layoutX="10.0" layoutY="10.0" prefHeight="250.0" prefWidth="300.0" spacing="10" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="FXFXML.FxFXMLController"><Button fx:id="okBtn" alignment="CENTER_RIGHT" contentDisplay="CENTER" mnemonicParsing="false" onAction="#printOutput" text="OK" textAlignment="CENTER" />

There are two special instance variables that can be declared in the controller and they are automatically injected by the FXML loader:

  • @FXML private URL location;
  • @FXML private ResourceBundle resources;

The location is the location of the FXML document. The resources is the reference of theResourceBundle. When the event handler attribute value starts with a hash symbol (#), it indicates to the FXML loader thatprintOutput() is the method in the controller, not in a script.

The event handler method in the controller should conform to some rules:

  • The method may take no arguments or a single argument. If it takes an argument, the argument type must be a type assignment compatible with the event it is supposed to handle.
  • Conventionally, the method return type should be void, because there is no taker of the returned value.
  • The method must be accessible to the FXML loader: make it public or annotate it with @FXML.
  • When the FXML loader is done loading the FXML document, it calls the initialize() method of the controller. The method should not take any argument. It should be accessible to the FXML loader. In the controller, you used the @FXML annotation to make it accessible to the FXML loader.

3.3 The Corresponding Java Class

FxFXMLExample3.java

import java.io.FileInputStream;import java.io.IOException;import javafx.application.Application;import javafx.fxml.FXMLLoader;import javafx.scene.Scene;import javafx.scene.layout.VBox;import javafx.stage.Stage;public class FxFXMLExample3 extends Application{public static void main(String[] args) {Application.launch(args);}@Overridepublic void start(Stage stage) throws IOException{// Create the FXMLLoader FXMLLoader loader = new FXMLLoader();// Path to the FXML FileString fxmlDocPath = "Path-To-Your-FXML-Files/FxFXMLExample3.fxml";FileInputStream fxmlStream = new FileInputStream(fxmlDocPath);// Create the Pane and all DetailsVBox root = (VBox) loader.load(fxmlStream);// Create the SceneScene scene = new Scene(root);// Set the Scene to the Stagestage.setScene(scene);// Set the Title to the Stagestage.setTitle("A FXML Example with a Controller");// Display the Stagestage.show();}}

3.4 The GUI

The following image shows the result of our program:

A JavaFX FXML Controller Example
A JavaFX FXML Controller Example

4. Download Java Source Code

This was an example JavaFX FXML Controller Example.

Download
You can download the full source code of this example here:JavaFxFXMLExample.zip
Do you want to know how to develop your skillset to become aJava Rockstar?
Subscribe to our newsletter to start Rockingright now!
To get you started we give you our best selling eBooks forFREE!
1. JPA Mini Book
2. JVM Troubleshooting Guide
3. JUnit Tutorial for Unit Testing
4. Java Annotations Tutorial
5. Java Interview Questions
6. Spring Interview Questions
7. Android UI Design
and many more ....
I agree to theTerms andPrivacy Policy

Thank you!

We will contact you soon.

Photo of Andreas PomarolliAndreas PomarolliApril 7th, 2016Last Updated: April 24th, 2019
1 6,431 11 minutes read
Photo of Andreas Pomarolli

Andreas Pomarolli

Andreas has graduated from Computer Science and Bioinformatics at the University of Linz. During his studies he has been involved with a large number of research projects ranging from software engineering to data engineering and at least web engineering. His scientific focus includes the areas of software engineering, data engineering, web engineering and project management. He currently works as a software engineer in the IT sector where he is mainly involved with projects based on Java, Databases and Web Technologies.

Related Articles

Bipartite Graph

JavaFX FXML Tutorial

April 14th, 2016
Subscribe
Notify of
guest
I agree to theTerms andPrivacy Policy
The comment form collects your name, email and content to allow us keep track of the comments placed on the website. Please read and accept our website Terms and Privacy Policy to post a comment.

I agree to theTerms andPrivacy Policy
The comment form collects your name, email and content to allow us keep track of the comments placed on the website. Please read and accept our website Terms and Privacy Policy to post a comment.