6 Using FXML to Create a User Interface (Release 8) (original) (raw)
This tutorial shows the benefits of using JavaFX FXML, which is an XML-based language that provides the structure for building a user interface separate from the application logic of your code.
If you started this document from the beginning, then you have seen how to create a login application using just JavaFX. Here, you use FXML to create the same login user interface, separating the application design from the application logic, thereby making the code easier to maintain. The login user interface you build in this tutorial is shown in Figure 6-1.
This tutorial uses NetBeans IDE. Ensure that the version of NetBeans IDE that you are using supports JavaFX 8. See the Certified System Configurations section of the Java SE Downloads page for details.
Set Up the Project
Your first task is to set up a JavaFX FXML project in NetBeans IDE:
- From the File menu, choose New Project.
- In the JavaFX application category, choose JavaFX FXML Application. Click Next.
- Name the project FXMLExample and click Finish.
NetBeans IDE opens an FXML project that includes the code for a basic Hello World application. The application includes three files:FXMLExample.java.
This file takes care of the standard Java code required for an FXML application.FXMLDocument.fxml.
This is the FXML source file in which you define the user interface.FXMLDocumentController.java.
This is the controller file for handling the mouse and keyboard input.
- Rename
FXMLDocumentController.java
to FXMLExampleController.java
so that the name is more meaningful for this application.- In the Projects window, right-click FXMLDocumentController.java and choose Refactor then Rename.
- Enter FXMLExampleController, and click Refactor.
- Rename
FXMLDocument.fxml
tofxml_example.fxml.
- Right-click FXMLDocument.fxml and choose Rename.
- Enter fxml_example and click OK.
Load the FXML Source File
The first file you edit is the FXMLExample.java
file. This file includes the code for setting up the application main class and for defining the stage and scene. More specific to FXML, the file uses the FXMLLoader
class, which is responsible for loading the FXML source file and returning the resulting object graph.
Make the changes shown in bold in Example 6-1.
Example 6-1 FXMLExample.java
@Override public void start(Stage stage) throws Exception { Parent root = FXMLLoader.load(getClass().getResource("fxml_example.fxml"));
Scene scene = new Scene(root, 300, 275);
stage.setTitle("FXML Welcome");
stage.setScene(scene);
stage.show();
}
A good practice is to set the height and width of the scene when you create it, in this case 300 by 275; otherwise the scene defaults to the minimum size needed to display its contents.
Modify the Import Statements
Next, edit the fxml_example.fxml
file. This file specifies the user interface that is displayed when the application starts. The first task is to modify the import statements so your code looks like Example 6-2.
Example 6-2 XML Declaration and Import Statements
As in Java, class names can be fully qualified (including the package name), or they can be imported using the import statement, as shown in Example 6-2. If you prefer, you can use specific import statements that refer to classes.
Create a GridPane Layout
The Hello World application generated by NetBeans uses an AnchorPane
layout. For the login form, you will use a GridPane
layout because it enables you to create a flexible grid of rows and columns in which to lay out controls.
Remove the AnchorPane
layout and its children and replace it with the GridPane
layout in Example 6-3.
Example 6-3 GridPane Layout
In this application, the GridPane
layout is the root element of the FXML document and as such has two attributes. The fx:controller
attribute is required when you specify controller-based event handlers in your markup. The xmlns:fx
attribute is always required and specifies the fx
namespace.
The remainder of the code controls the alignment and spacing of the grid pane. The alignment property changes the default position of the grid from the top left of the scene to the center. The gap
properties manage the spacing between the rows and columns, while the padding
property manages the space around the edges of the grid pane.
As the window is resized, the nodes within the grid pane are resized according to their layout constraints. In this example, the grid remains in the center when you grow or shrink the window. The padding properties ensure there is a padding around the grid when you make the window smaller.
Add Text and Password Fields
Looking back at Figure 6-1, you can see that the login form requires the title ”Welcome” and text and password fields for gathering information from the user. The code in Example 6-4 is part of the GridPane
layout and must be placed above the </GridPane>
statement.
Example 6-4 Text, Label, TextField, and Password Field Controls
<Label text="User Name:"
GridPane.columnIndex="0" GridPane.rowIndex="1"/>
<TextField
GridPane.columnIndex="1" GridPane.rowIndex="1"/>
<Label text="Password:"
GridPane.columnIndex="0" GridPane.rowIndex="2"/>
<PasswordField fx:id="passwordField"
GridPane.columnIndex="1" GridPane.rowIndex="2"/>
The first line creates a Text
object and sets its text value to Welcome
. The GridPane.columnIndex
and GridPane.rowIndex
attributes correspond to the placement of the Text
control in the grid. The numbering for rows and columns in the grid starts at zero, and the location of the Text
control is set to (0,0), meaning it is in the first column of the first row. The GridPane.columnSpan
attribute is set to 2, making the Welcome title span two columns in the grid. You will need this extra width later in the tutorial when you add a style sheet to increase the font size of the text to 32 points.
The next lines create a Label
object with text User Name
at column 0, row 1 and a TextField
object to the right of it at column 1, row 1. Another Label
and PasswordField
object are created and added to the grid in a similar fashion.
When working with a grid layout, you can display the grid lines, which is useful for debugging purposes. In this case, set the gridLinesVisible
property to true
by adding the statement <gridLinesVisible>true</gridLinesVisible>
right after the <padding></padding>
statement. Then, when you run the application, you see the lines for the grid columns and rows as well as the gap properties, as shown in Figure 6-2.
Add a Button and Text
The final two controls required for the application are a Button
control for submitting the data and a Text
control for displaying a message when the user presses the button. The code is in Example 6-5. Add this code before </GridPane>
.
Example 6-5 HBox, Button, and Text
An HBox
pane is needed to set an alignment for the button that is different from the default alignment applied to the other controls in the GridPane
layout. The alignment
property is set to bottom_right
, which positions a node at the bottom of the space vertically and at the right edge of the space horizontally. The HBox
pane is added to the grid in column 1, row 4.
The HBox
pane has one child, a Button
with text
property set to Sign in
and an onAction
property set to handleSubmitButtonAction()
. While FXML is a convenient way to define the structure of an application's user interface, it does not provide a way to implement an application's behavior. You implement the behavior for the handleSubmitButtonAction()
method in Java code in the next section of this tutorial, Add Code to Handle an Event.
Assigning an fx:id
value to an element, as shown in the code for the Text
control, creates a variable in the document's namespace, which you can refer to from elsewhere in the code. While not required, defining a controller field helps clarify how the controller and markup are associated.
Add Code to Handle an Event
Now make the Text
control display a message when the user presses the button. You do this in the FXMLExampleController.java
file. Delete the code that NetBeans IDE generated and replace it with the code in Example 6-6.
Example 6-6 FXMLExampleController.java
package fxmlexample;
import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.text.Text;
public class FXMLExampleController { @FXML private Text actiontarget;
@FXML protected void handleSubmitButtonAction(ActionEvent event) {
actiontarget.setText("Sign in button pressed");
}
}
The @FXML
annotation is used to tag nonpublic controller member fields and handler methods for use by FXML markup. The handleSubmtButtonAction
method sets the actiontarget
variable to Sign in button pressed
when the user presses the button.
You can run the application now to see the complete user interface. Figure 6-3 shows the results when you type text in the two fields and click the Sign in button. If you have any problems, then you can compare your code against the FXMLLogin example.
Use a Scripting Language to Handle Events
As an alternative to using Java code to create an event handler, you can create the handler with any language that provides a JSR 223-compatible scripting engine. Such languages include JavaScript, Groovy, Jython, and Clojure.
Optionally, you can try using JavaScript now.
- In the file
fxml_example.fxml
, add the JavaScript declaration after the XML doctype declaration.<?language javascript?>
- In the
Button
markup, change the name of the function so the call looks as follows:onAction="handleSubmitButtonAction(event);"
- Remove the
fx:controller
attribute from theGridPane
markup and add the JavaScript function in a<script>
tag directly under it, as shown in Example 6-7.
Example 6-7 JavaScript in FXML
fx:script
function handleSubmitButtonAction() {
actiontarget.setText("Calling the JavaScript");
}
Alternatively, you can put the JavaScript functions in an external file (such as fxml_example.js
) and include the script like this:<fx:script source="fxml_example.js"/>
The result is in Figure 6-4.
If you are considering using a scripting language with FXML, then note that an IDE might not support stepping through script code during debugging.
Style the Application with CSS
The final task is to make the login application look attractive by adding a Cascading Style Sheet (CSS).
- Create a style sheet.
- In the Project window, right-click the fxmlexample folder under Source Packages and choose New, then Other.
- In the New File dialog box, choose Other, then Cascading Style Sheet and click Next.
- Enter Login and click Finish.
- Copy the contents of the
Login.css
file into your CSS file. TheLogin.css
file is included in the downloadable LoginCSS.zip file. For a description of the classes in the CSS file, see Fancy Forms with JavaFX CSS.
- Download the gray, linen-like image for the background by right-clicking the background.jpg file and saving it to the
fxmlexample
folder. - Open the
fxml_example.fxml
file and add a stylesheets element before the end of the markup for theGridPane
layout as shown in Example 6-8.
Example 6-8 Style Sheet
The @ symbol before the name of the style sheet in the URL indicates that the style sheet is in the same directory as the FXML file. - To use the root style for the grid pane, add a style class to the markup for the
GridPane
layout as shown in Example 6-9.
Example 6-9 Style the GridPane - Create a
welcome-text
ID for the WelcomeText
object so it uses the style#welcome-text
defined in the CSS file, as shown in Example 6-10.
Example 6-10 Text ID - Run the application. Figure 6-5 shows the stylized application. If you run into problems, then take a look at the code that is included in the downloadable FXMLExample.zip file
Where to Go from Here
Now that you are familiar with FXML, look at Introduction to FXML, which provides more information on the elements that make up the FXML language. The document is included in the javafx.fxml
package in the API documentation.
You can also try out the JavaFX Scene Builder tool by opening the fxml_example.fxml
file in Scene Builder and making modifications. This tool provides a visual layout environment for designing the UI for JavaFX applications and automatically generates the FXML code for the layout. Note that the FXML file might be reformatted when saved. See the Getting Started with JavaFX Scene Builder for more information on this tool. The Skinning with CSS and the CSS Analyzer section of the JavaFX Scene Builder User Guide also gives you information on how you can skin your FXML layout.