JavaFX replicates the web technology structure of HTML, JavaScript and CSS in its application of FXML, Java controllers and CSS code. As you might hope, linking up a controller in JavaFX is similar to the web-tech structure it replicates.

The confusion surrounding how to link a controller with an application usually arises because as Java developers, we’re used to doing everything in Java code. In the JavaFX model (especially in a simple app) the opposite is true.

JavaFX’s FXML document is designed to replicate the HTML of web design. It’s in this document that you should include all of the links to both the controller and to the CSS files you need for styling.

How it works in web apps:

In a website, the browser requests the HTML from a web server, which asks for extra files when it needs them. The HTML file acts as the anchor, which defines the basic structure of a website, but also handles requests to JavaScript and CSS resources.

Websites are structured using JavaScript, HTML and CSS

There are a few extra bits like asynchronous scripts and in-line scripts/CSS, but with the exception of JavaScript-driven asynchronous requests, the HTML document still acts as that anchor.

In JavaFX, we start in the Main class, which replicates the actions of the Browser.

How it works in JavaFX

The JavaFX application actually has to do some of the job of the browser, loading up the window for the application before the users can interact with it. This happens in the start() method

JavaFX structure replicates both the work of a browser, and a webpage

The Main method usually loads up the FXML file using code similr to this:

FXMLLoader fxmlLoader = new FXMLLoader(
        App.class.getResource("fxml/mainView.fxml"));    //Tell the FXMLLoader where the FXML file is
Parent rootNode = fxmlLoader.load();                     //create the view and link it with the Controller

Once the Main class has loaded up the FXML file, the FXML file completely replicates the role played by the HTML file in the web-tech model, as a link to Java controller and CSS files.

An application’s View should be linked with its Controller inside the start() method of the JavaFX application. Links should be created by storing a reference to the Java controller inside the FXML file. This is then automatically linked when the FXMLLoader creates the View.

The structure of a JavaFX FXML file and the reference to the Controller

In applications with more than one View, you should create a link from a View to its Controller whenever the FXMLLoader reads an FXML document into memory. In each case, you should store the links from the View to the Controller inside the FXML document. That way, the FXMLLoader can automatically create the connections as it reads the file.

What does the rest of the code in start() do?

The code inside the start() method of a JavaFX application must perform two functions:

  1. The initial code in the Main class. This does the job of the Browser, as it creates and shows a window to display our app.
  2. The other code involving the FXMLLoader creates a View and links your interface with the Controller

In simple cases, where we have one window and one controller, you can visualise the Main class’s start(Stage stage) method like so:

The main method of a JavaFX application predominantly deals with Application Lifecycle and not with the behaviour of the app
The main method of a JavaFX application predominantly deals with Application Lifecycle and not with the FXML and the view

In the vast majority of simple cases, the lifecycle code like starting up the window doesn’t do anything to link your app with your controller.

All of the linking between the FXML and Controller happens when the FXMLLoader object reads the FXML file into memory.

Linking an interface with a Controller using the FXMLLoader

Once we’re happy with the lifecycle code in the start() method, which sets about creating and showing a window to our users, we’re left with two or three lines of code. These lines create the View (the interface), and connect it with Java Controller.

Here are those lines of code:

FXMLLoader fxmlLoader = new FXMLLoader(
        App.class.getResource("fxml/mainView.fxml"));    //Tell the FXMLLoader where the FXML file is
Parent rootNode = fxmlLoader.load();                     //create the view and link it with the Controller
stage.setScene(new Scene(rootNode));                     //display the view in this window please

In a JavaFX application, the FXMLLoader creates a View by reading an FXML file into memory. As part of that process, it creates objects for each of the Layouts, Controls, Shapes and Charts that you’ve defined.

A Simple JavaFX Scene Graph

JavaFX defines a View as a collection of Java objects in memory, which are collectively called the Scene Graph.. This is similar to the Domain Object Model in HTML, which is also a tree-like structure of elements in a view. In the background, JavaFX maps each of these objects to a rendering pipeline that displays your app on the screen.

As the FXMLLoader reads the FXML file into memory, it creates links with the controller automatically. These links need to be defined within the FXML document itself. Those links are defined in the next section.

When the FXMLLoader parses the FXML file below, it extracts structural, layout, and object information, as well as links to the Java Controller (highlighted call-outs in blue).

The structure of a JavaFX FXML file

As the FXMLLoader parses the FXML file, it also picks up on links to objects that are intended to be directly accessed by the Controller object. These can be physical objects like a layout or control, or can be events like pressing a button (highlighted in dark blue).

Below are the basic links that should be included in an FXML file. These will connect the View to the Controller and allow it to access the View directly.

LinkPlacementMeaning
fx:controllerAs an attribute in the root element (the VBox in this example)The fully qualified name of the Controller
fx:idAs an attribute of any object (layout, control, shape etc.)Individual scene objects that you want to directly reference from the Controller.
onAction
(and other events)
As an attribute of objects with defined event PropertiesA link to a method in the Controller, which must take an Event as a parameter.

This is how those parameters look in a real FXML file, and how they map to the Controller object itself.

The FXML file contains links to the Controller as well as directly to objects in the view and events

Advanced concepts

There are a number of advanced concepts, like dependency injection, expression binding and multiple View-Controller relationships. You can also define these inside an FXML document for more

Check out these links to see more information about each:

Conclusions

In most simple cases, you should connect an app’s View with its Controller during initialisation, when the FXMLLoader reads an FXML file into memory.

Connections to the Java Controller object should be defined within the FXML file by including a fx:controller attribute inside the root node. The root node is the first listed in the FXML document. All other nodes are nested inside this one.

The root node of an FXML file

Other direct links can be created between a View and its controller by including fx:id attributes, and event references, wherever suitable convenience methods are available for that object.