A Simple FXML document outlining an AnchorPane
containing a button and a label node:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="com.example.FXMLDocumentController">
<children>
<Button layoutX="126" layoutY="90" text="Click Me!" onAction="#handleButtonAction" fx:id="button" />
<Label layoutX="126" layoutY="120" minHeight="16" minWidth="69" fx:id="label" />
</children>
</AnchorPane>
This example FXML file is associated with a controller class. The association between the FXML and the controller class, in this case, is made by specifying the class name as the value of the fx:controller
attribute in the root element of the FXML: fx:controller="com.example.FXMLDocumentController"
. The controller class allows for Java code to be executed in response to user actions on the UI elements defined in the FXML file:
package com.example ;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
public class FXMLDocumentController {
@FXML
private Label label;
@FXML
private void handleButtonAction(ActionEvent event) {
System.out.println("You clicked me!");
label.setText("Hello World!");
}
@Override
public void initialize(URL url, ResourceBundle resources) {
// Initialization code can go here.
// The parameters url and resources can be omitted if they are not needed
}
}
An FXMLLoader
can be used to load the FXML file:
public class MyApp extends Application {
@Override
public void start(Stage stage) throws Exception {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("FXMLDocument.fxml"));
Parent root = loader.load();
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
}
The load
method performs several actions, and it is useful to understand the order in which they happen. In this simple example:
The FXMLLoader
reads and parses the FXML file. It creates objects corresponding to the elements defined in the file, and makes note of any fx:id
attributes defined on them.
Since the root element of the FXML file defined a fx:controller
attribute, the FXMLLoader
creates a new instance of the class that it specifies. By default this happens by invoking the no-argument constructor on the class specified.
Any elements with fx:id
attributes defined which have fields in the controller with matching field names, and which are either public
(not recommended) or annotated @FXML
(recommended) are "injected" into those corresponding fields. So in this example, since there is a Label
in the FXML file with fx:id="label"
and a field in the controller defined as
@FXML
private Label label ;
the label
field is initialized with the Label
instance created by the FXMLLoader
.
Event handlers are registered with any elements in the FXML file with onXXX="#..."
properties defined. These event handlers invoke the specified method in the controller class. In this example, since the Button
has onAction="#handleButtonAction"
, and the controller defines a method
@FXML
private void handleButtonAction(ActionEvent event) { ... }
when an action is fired on the button (e.g. the user presses it), this method is invoked. The method must have void
return type, and can either define a parameter matching the event type (ActionEvent
in this example), or can define no parameters.
Finally, if the controller class defines an initialize
method, this method is invoked. Notice this happens after the @FXML
fields have been injected, so they can be safely accessed in this method and will be initialized with the instances corresponding to the elements in the FXML file. The initialize()
method can either take no parameters, or can take a URL
and a ResourceBundle
. In the latter case, these parameters will be populated by the URL
representing the location of the FXML file, and any ResourceBundle
set on the FXMLLoader
via loader.setResources(...)
. Either of these can be null
if they were not set.