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 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
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.
When do you link the interface with it’s controller?
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.
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:
- 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.
- The other code involving the
FXMLLoadercreates a View and links your interface with the Controller
In simple cases, where we have one window and one controller, you can visualise the
start(Stage stage) method like so:
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.
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.
Defining links between your FXML file and Controller
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).
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).
Basic FXML links to Controller
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.
|fx:controller||As an attribute in the root element (the VBox in this example)||The fully qualified name of the Controller|
|fx:id||As an attribute of any object (layout, control, shape etc.)||Individual scene objects that you want to directly reference from the Controller.|
(and other events)
|As an attribute of objects with defined event Properties||A 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.
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:
- Simple dependency injection to create and link Controllers with pre-made Views
- Using Expression Binding to connect values in your FXML file with values in your Controller.
- Including multiple FXML files or references inside a single View
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.
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.