Skip to main content
Blog

JavaFX GUI development: FXML vs Java code

By 26 september 2014januari 30th, 2017No Comments

Introduction

Recently I worked on a project which used JavaFX 8. We needed to create a JavaFX application capable of manipulating XML files. Having little knowledge about JavaFX, I started out doing some research. As one would expect, Google is your biggest friend. It immediately became clear there are two ways of creating user interfaces in JavaFX. You can construct the user interface using Java code, or make use of FXML to describe the user interface. In this post I write about different ways to build a solid GUI in JavaFX and its architecture and about the tooling I used.

FXML

FXML is an XML based language for defining the structure of a GUI in JavaFX. Because FXML isolates the view code from the model and controller code, this is a perfect way to implement the MVC design pattern. FXML works by defining the structure of your GUI in a *.fxml file. The FXML file can then be used to bootstrap the user interface. This way of defining the user interface is quite different from defining it in Java code. Let’s have a look at the differences between building a GUI using Swing-style Java code and using FXML.

The listing below represents a Swing-style Java code implementation of an example GUI:


// Define the root layout pane
BorderPane root = <strong>new</strong> BorderPane();

// The scene is your container for all components with the
// layout pane as root
Scene scene = <strong>new</strong> Scene(root, 400, 400);

// Define some GUI controls
ListView<String> listView = <strong>new</strong> ListView<String>();
observableList.addAll(model);
listView.setItems(observableList);
Label label = <strong>new</strong> Label("Items:");

// And add them to the layout pane
root.setTop(label);
root.setCenter(listView);

// The stage is your window in JavaFX
stage.setScene(scene);
stage.setTitle("Example");
stage.show();

Listing 1: GUI definition using Swing-style Java code

Listing 1 is a fragment of the main class that is used to run the application. I start by creating a layout pane for my GUI components and add it as the root component to the scene. After that I create the GUI components and finally add the scene to the stage (which acts as the window). Everything here is done inside the main class. If I would create a button, then its behavior will also be defined here.

In the next listing I am showing the different parts of the FXML implementation of the same GUI.

Main class:


…
// Load the FXML
URL location = getClass().getResource("Example.fxml");
FXMLLoader fxmlLoader = new FXMLLoader(location);
Parent root = fxmlLoader.load();

// Create the scene and setup the stage
Scene scene = new Scene(root, 400, 400);
stage.setTitle("Example");
stage.setScene(scene);
stage.show();
…

View (FXML) code:


<BorderPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.FxmlController">
<top>
<Label text="Items:" BorderPane.alignment="CENTER" />
</top>
<center>
<ListView fx:id="listView" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER" />
</center>
</BorderPane>

Controller code:


…
@FXML
private ListView<String> listView;

private ObservableList<String> observableList =
FXCollections.observableArrayList();

public void initialize() {
observableList.addAll(model);
listView.setItems(observableList);
}

Listing 2: GUI definition using FXML

In listing 2 I have separated the view and controller code. The GUI components that were created inside the Java code in listing 1 are moved to the FXML file and are injected into the controller by using the @FXML annotation. Only two steps are needed to allow access to the GUI components in the controller like the ListView in this example.

  1. Define the controller in the root element of your FXML (fx:controller=”…”);
  2. Provide an id for your GUI component (fx:id=”…”). This id matches your field name.

If I would add a button trough this approach I could add a click handler directly in the controller by injecting the button and changing its behavior (see listing 3). I prefer this method as it separates the view even more from the controller and everything but the GUI declaration is found in the Java code.

In the FXML:


<Button fx:id=<em>"add"</em> text=<em>"Add"</em> />

In the controller:


@FXML
private Button add;
…
add.setOnAction(actionEvent -> {
// do Stuff...
});

Listing 3: Assigning behavior from the controller

It is also possible to refer to a method in the controller from within the FXML. This method must then be annotated with @FXML (see listing 4).

In the FXML:


<Button text=<em>"Add"</em> onAction=<em>"#addItem"</em> />

In the controller:


@FXML
public void addItem(ActionEvent action) {
// do stuff...
}

Listing 4: Assigning behavior from the view

In these examples I have created a simple GUI containing only a label and a listview. In my project I had to create multiple large forms that represent the XML file that is loaded. Implementing that by following listing 1 would create chaos (imagine all GUI elements and behavior in one class), while listing 2 contains multiple clear FXML files and controllers. Because I used FXML, I was able to easily nest FXML files and have each nested view use its own controller.


<fx:include source=<em>"another.fxml"</em> />

Listing 5: Including another FXML file

Tooling

I recommend a beginning JavaFX FXML developer to start with using the Scene Builder tool. The JavaFX Scene Builder is a free tool that can be downloaded from the Oracle website and allows you to define your GUI (and generate an FXML file) using a drag & drop interface.

Another way is to write your own FXML using the E(fx)clipse platform. This is a standalone Eclipse distribution that comes with some plugins to bootstrap your JavaFX project and support code completion for e.g. FXML and CSS. These plugins can also be installed in your favorite Eclipse version.

Conclusion

This concludes the first part of my JavaFX blog. In the coming blog posts I will dig deeper into the following features:

  • Scene Builder and E(fx)clipse;
  • The different layout panes;
  • Binding the view to the model, including bidirectional binding;
  • The application thread.

Sources

Java SE 8 docs:

http://docs.oracle.com/javase/8/docs/
http://docs.oracle.com/javase/8/javase-clienttechnologies.htm

JavaFX 8 API reference

http://docs.oracle.com/javase/8/javafx/api/toc.htm

Introduction to FXML:

http://docs.oracle.com/javase/8/javafx/api/javafx/fxml/doc-files/introduction_to_fxml.html

Scene builder:

http://www.oracle.com/technetwork/java/javase/downloads/sb2download-2177776.html

E(fx)clipse:

http://www.eclipse.org/efxclipse/index.html