6 Implementing a Swing Application in JavaFX
In this chapter, you consider a Swing application and learn how to implement it in JavaFX.
For the purpose of this chapter, get familiar with the Converter
application shown in Figure 6-1. This application converts distance measurements between metric and U.S. units.
Analyzing the Converter Application Developed in Swing
For more information about the implementation of this example in the Java programming language, see How to Use Panels and Using Models trails in the Swing tutorial. In particular, the graphical user interface (GUI) is discussed in the trail about the panels.
To learn the code of the Converter application, download its NetBeans project or the source files available at the example index.
Swing components use models. If you look at the contents of the project, you notice the ConverterRangeModel
and FollowerRangeModel
classes that define models for the Converter application.
The Converter application consists of the following files:
-
ConversionPanel.java
— contains a customJPanel
subclass to hold components -
Converter.java
— contains the main application class -
ConverterRangeModel.java
— defines the top slider's model -
FollowerRangeModel.java
— defines the bottom slider's model -
Units.java
— createsUnit
objects
Note that the synchronization between each text field and its slider is implemented by event handlers that listen for changes in values.
Planning the Converter Application in JavaFX
The Converter
application contains two similar panels that hold components such as a text field, slider, and combo box. The panels have titles. The TitlePane
class from the javafx.scene.control package ideally suits the GUI of the Converter
application.
In what follows, you will implement the ConversionPanel
class and add two instances of this class to the graphical scene of the Converter
application.
First, note that the components within a single ConversionPanel
object should be synchronized as follows. Whenever you move the knob on the slider, you must update the value in the text field and vice versa: Whenever you change the value in the text field, you must adjust the position of the knob on the slider.
As soon as you choose another value from the combo box, you must update the value of the text field and, hence, the position of the knob on the slider.
Second, note that both ConversionPanel
objects should be synchronized. As soon as changes happen on one panel, the corresponding components on another panel must be updated.
It is suggested that you implement synchronization between the panels using the DoubleProperty
object, called meters
, and listen to changes in the properties of the text fields and combo boxes by creating and registering two InvalidationListener
objects: fromMeters
and toMeters
. Whenever the property of the text field on one panel changes, the invalidated
method of the attached InvalidationListener
object is called, which updates the meters
property. Because the meters
property changes, the invalidated
method of the InvalidationListener
object, attached to the meters
property, is called, which updates the corresponding text field on another panel.
Similarly, whenever the property of the combo box on one panel changes, the invalidated
method of the attached InvalidationListener
object is called, which updates the text field on this panel.
To provide synchronization between the value of the slider and the value of the meters
object, use bidirectional binding.
For more information about JavaFX properties and binding, see Using JavaFX Properties and Binding.
Creating the Converter Application in JavaFX
Create a new JavaFX project in NetBeans IDE and name it Converter. Copy the Unit.java
file from the Swing application to the Converter project. Add a new java class to this project and name it ConversionPanel.java
.
Standard JavaFX Pattern to Create the GUI
Before you start creating the GUI of the Converter
application in JavaFX, see the standard pattern of GUI creation in Swing applications, as shown in Example 6-1.
Example 6-1
public class Converter { private void initAndShowGUI() { ... } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { initAndShowGUI(); } }); } }
To map this pattern to JavaFX, you extend the javafx.application.Application
class, override the start
method, and call the main
method, as shown in Example 6-2.
Example 6-2
import javafx.application.Application; import javafx.stage.Stage; public class Converter extends Application { @Override public void start(Stage t) { ... } public static void main(String[] args) { launch(args); } }
When you create a new JavaFX project in the NetBeans IDE, this pattern is automatically generated for you. However, it is important that you understand the basic approach to GUI creation in JavaFX, especially if you use a text editor.
Containers and Layouts
In Swing, containers and layout managers are different entities. You create a container, such as a JPanel
or JComponent
object, and set a layout manager for this container. You can assign a specific layout manager and write.add()
in your code or assign none of the layout managers.
In JavaFX, the container itself takes care of laying out its child nodes. You create a specific layout pane, such as a Vbox
, FlowPane
, or TitledPane
object, and then add content to the list of its child nodes using the.getChildren().add()
methods.
There are several layout container classes in JavaFX, called panes, some of which have their counterparts in Swing, such as the FlowPane
class in JavaFX and FlowLayout
class in Swing.
For more information, see Working With Layouts in JavaFX.
UI Controls
JavaFX SDK provides a set of standard UI controls. Some of the UI controls have their counterparts in Swing such as the Button
class in JavaFX and JButton
in Swing; Slider
in JavaFX and JSlider
in Swing; and TextField
in JavaFX and JTextField
in Swing.
To implement the Converter
application in JavaFX, you can use the standard UI controls provided by the TextField
, Slider
, and ComboBox
classes.
For more information, see Using JavaFX UI Controls.
Mechanism of Getting Notifications on User Actions and Binding
In Swing, you can register a listener on any component and listen for changes in the component properties, such as size, position, or visibility; or listen for events, such as whether the component gained or lost the keyboard focus; or whether the mouse was clicked, pressed, or released over the component.
In JavaFX, each object has a set of properties for which you can register a listener. The listener is called whenever a value of the property changes.
Note that an object can be registered as a listener for changes in another object's properties. Thus, you can use the binding mechanism to synchronize some properties of two objects.
Creating the ConversionPanel Class
The ConversionPanel
class is used to hold components: a text field, a slider, and a combo box. When creating the graphical scene of the Converter
application, you add two instances of the ConversionPanel
class to the graphical scene. Add the import statement for the TitledPane
class and extend the ConversionPanel
class as shown in Example 6-3.
Example 6-3
import javafx.scene.control.TitledPane; public class ConversionPanel extends TitledPane { }
Creating Instance Variables for UI Controls
Add import statements for the TextField
, Slider
, ComboBox
controls and define instance variables for the components as shown in Example 6-4.
Creating DoubleProperty and NumberFormat Objects
Add the import statement for the DoubleProperty
and NumberFormat classes and create a DoubleProperty
object named meters
as shown in Example 6-5. The meters
object is used to ensure the synchronization between two ConversionPanel
objects.
Laying Out the Components
To lay out the text field and the slider, use the VBox
class. To lay out both of these components and a combo box, use the HBox
class. Add the import statements for the ObservableList
class and implement the constructor of the ConversionPanel
class as shown in Example 6-6.
Example 6-6
import javafx.collections.ObservableList; public ConversionPanel(String title, ObservableList<Unit> units, DoubleProperty meters) { setText(title); setCollapsible(false); numberFormat = NumberFormat.getNumberInstance(); numberFormat.setMaximumFractionDigits(2); textField = new TextField(); slider = new Slider(0, MAX, 0); comboBox = new ComboBox(units); comboBox.setConverter(new StringConverter<Unit>() { @Override public String toString(Unit t) { return t.description; } @Override public Unit fromString(String string) { throw new UnsupportedOperationException("Not supported yet."); } }) VBox vbox = new VBox(textField, slider); HBox hbox = new HBox(vbox, comboBox); setContent(hbox); this.meters = meters; comboBox.getSelectionModel().select(0); }
The last line of code selects a value in the ComboBox
object.
Creating InvalidationListener Objects
To listen to changes in the properties of the text fields and combo boxes, create the InvalidationListener
objects fromMeters
and toMeters
as shown in Example 6-7.
Example 6-7
import javafx.beans.InvalidationListener; private InvalidationListener fromMeters = t -> { if (!textField.isFocused()) { textField.setText(numberFormat.format(meters.get() / getMultiplier())); } }; private InvalidationListener toMeters = t -> { if (!textField.isFocused()) { return; try { meters.set(numberFormat.parse(textField.getText()).doubleValue() * getMultiplier()); } catch (ParseException | Error | RuntimeException ignored) { } };
Adding Change Listeners to Controls and Ensuring Synchronization
To provide the synchronization between the text fields and combo boxes, add change listeners as shown in Example 6-8.
Example 6-8
meters.addListener(fromMeters); comboBox.valueProperty().addListener(fromMeters); textField.textProperty().addListener(toMeters); fromMeters.invalidated(null);
Create a bidirectional binding between the value of the slider and the value of the meters
object as shown in Example 6-9.
When a new value is typed in the text field, the invalidated
method of the toMeters
listener is called, which updates the value of the meters
object.
Creating the Converter Class
Open the Converter.java
file that was automatically generated by the NetBeans IDE and remove all of the code except for the main
method. Then, press Ctrl (or Cmd)+Shift+I to correct the import statements.
Defining Instance Variables
Add import statements for the ObservableList
, DoubleProperty
, and SimpleDoubleProperty
classes and create metricDistances
, usaDistances
, and meters
variables of the appropriate types as shown in Example 6-10.
Example 6-10
import javafx.beans.property.DoubleProperty; import javafx.collections.ObservableList; import javafx.beans.property.SimpleDoubleProperty; private ObservableList<Unit> metricDistances; private ObservableList<Unit> usaDistances; private DoubleProperty meters = new SimpleDoubleProperty(1);
Creating the Constructor for the Converter Class
In the constructor for the Converter
class, create Unit
objects for the metric and the U.S. distances as shown in Example 6-11. Add the import statement for the FXCollections
class. Later, you will instantiate two ConversionPanel
objects with these units.
Example 6-11
import javafx.collections.FXCollections; public Converter() { metricDistances = FXCollections.observableArrayList( new Unit("Centimeters", 0.01), new Unit("Meters", 1.0), new Unit("Kilometers", 1000.0)); usaDistances = FXCollections.observableArrayList( new Unit("Inches", 0.0254), new Unit("Feet", 0.305), new Unit("Yards", 0.914), new Unit("Miles", 1613.0)); }
Creating the Graphical Scene
Override the start
method to create the graphical scene for your Converter
application. Add two ConversionPanel
objects to the graphical scene and lay out them vertically. Note that two ConversionPanel
objects are instantiated with the same meters
object. Use the VBox
class as a root container for the graphical scene. Instantiate two ConversionPanel
objects as shown in Example 6-12.
Example 6-12
@Override public void start(Stage stage) { VBox vbox = new VBox( new ConversionPanel( "Metric System", metricDistances, meters), new ConversionPanel( "U.S. System", usaDistances, meters)); Scene scene = new Scene(vbox); stage.setTitle("Converter"); stage.setScene(scene); stage.show(); }
You can view the source code and download the NetBeans project of the Converter
application in JavaFX using the links at the bottom of this document.
The Converter application in JavaFX is shown in Figure 6-2.
Figure 6-2 Converter Application in JavaFX

Description of "Figure 6-2 Converter Application in JavaFX"
Compare the two applications with the same functionality implemented using the Swing library and JavaFX.
Not only does the application in JavaFX contain three files as compared with five files of the Swing application, but the code in JavaFX is cleaner. The applications also differ in look and feel.