JavaFX is easy once you get the hang of it, but for new programmers that requires plenty of examples. More experienced programmers will find one or two examples are enough to master most of JavaFX, so a lot of web sites only put one or two examples up—enough for experienced programmers, but not nearly enough for newer programmers.
In this post, I present the classic temperature converter example modified to use JavaFX. This example uses basic MVC/MVP design. If you want to see this same JavaFX tutorial written in pure Java, look for my other tutorial on this site. It will be the one mentioning pure Java instead of FXML.
Creating a JavaFX Project in Eclipse
In Eclipse create a JavaFX project by selecting File->New->Project… from the menu bar. You will need e(fx)clipse installed in your Eclipse to create a JavaFX project.
You can put minimal information in, and create the project. You can modify it by hand, later.
Choose a name for your JavaFX project and select finished. You end up with a Main class, an application CSS file and some JavaFX libraries. Not too much, but we’ll add more to the project and make it work.
First thing’s first. You probably don’t have the package name you want. I suggest creating the package name you like and move the CSS and Java files into it. I used whatisjavafx.com for package name, but you can pick one you like. Just modify the code examples in this tutorial to match the package structure you want.
First, let’s swap out the code in Main.java with our own. Use the following code. Remember to change the package name if necessary.
The Main class extends javafx.application.Application as do all main classes for JavaFX projects. Obviously, you could rename your Main class to be any name you want, but it still needs to extend Application.
Be sure to call launch() in your main() method. The launch() method is what starts your JavaFX. It ends up calling the start() method that gives us the stage for our JavaFX app. Remember, all the JavaFX’s a stage. (It had to be said.)
In the start() method, we load the convert.fxml file. We haven’t created the convert.fxml file, yet. We will, soon.
FXML files have a Parent as a root. In our case, it is a VBox. But it could be any class that inherits from Parent. A Parent in the scene graph could be a box, pane, or any other container. Look over the selection of Parents in the Container list next time you have Scene Builder open to get a feel for the types of Parents you could use as your root.
You’ll see in the Main class that we don’t include a width and height when configuring the scene to add to the stage. The reason is that we set the VBox width and height in the FXML using Scene Builder.
In short, the start() method loads the FXML description of our window. Then the FXML is placed in a Parent object, which is placed in a Scene, that is finally placed in a Stage and made visible using the show() method.
FXML Creation with Scene Builder
Next, let’s get our FXML ready. We’re going to use Scene Builder to create it. However, if you don’t care about Scene Builder, or just want to take a shortcut. Create a file named convert.fxml in the same directory as your Main class and place the following XML into it.
Before constructing the FXML using Scene Builder, take a look at the provided FXML, above. It starts in the same way as countless XML files, with a version and encoding information. You’ll find that FXML starts with import statements very similar to the way Java classes start.
After the initial imports, you see a very easy-to-read Scene node graph. Each container is listed (like VBox and HBox), followed by its children. The layout is very easy to follow. Most people find the JavaFX layouts presented in FXML formatting to be easier understand than the same layouts given in pure Java.
Here’s how you create that FXML above using Scene Builder. If you have not set up Eclipse to edit FXML files with Scene Builder, yet, open your Eclipse workspace preferences from the Eclipse menu bar, and select JavaFX. You should see a JavaFX dialog allowing you to set the location of your Scene Builder executable. Once the Scene Builder executable is set, it is far easier to open FXML files from inside Eclipse for editing in Scene Builder.
You won’t need this configuration to create your FXML file. But, if you want to modify your FXML file after you close Scene Builder, this configuration makes your life a little more peaceful.
Go ahead and open your Scene Builder. You should have a blank UI. You create your UI by dragging containers and other nodes from the left onto the middle design area. You configure those nodes using the area on the right.
A useful feature on the left is the Hierarchy section. The Hierarchy shows the nodes and their arrangement visually. It makes it easy to see what nodes are where on the UI. The Hierarchy also make is easy to select hard-to-click nodes in your layout.
The Hierarchy above describes the root node for our temperature conversion window. Create a layout similar to this one by dragging a VBox to the center area of SceneBuilder. Then drag two HBoxes and a Button out to fill the first three rows of the VBox. Then drag Labels and TextFields out to the HBoxes.
You should end up with a Hierarchy that looks like that pictured above. Don’t worry that the layout doesn’t look like the final layout, yet. The devil’s in the configurations. We’ll deal with that in a moment. First get the nodes in the scene graph in the correct hierarchy.
At this point any normal person is asking, What are VBoxes and HBoxes? Don’t worry. That’s a normal question.
Labels, Buttons and TextFields are somewhat obvious and self-describing. However, VBox and HBox isn’t quite as simple. VBoxes and HBoxes are what are called Containers. Containers hold things like Labels and Buttons. You add Components to Containers, and the Containers automagically layout the components for you. There is a whole are to choosing and combining Containers in a way that makes your application look professional. Look for other tutorials on this site dealing with that art.
VBox containers layout design elements in a line starting at the top of the window, and going down with each new component added. HBox containers line up components from left to right as they are added. VBox and HBox are only to containers of a whole collection of possible containers that JavaFX provides. However, by combining just these two types of containers, you can come up with some pretty sophisticated UI layouts.
Note: If the first couple of tries at creating the layout for the temperature conversion window don’t work out. Just start fresh by selecting
from the Scene Builder menu. Nothing to be ashamed of. You’re just learning after all.
Focus first on getting the hierarchy that you want. Once the hierarchy looks correct, fix your labels to say what you want by double clicking on them. Once you double click on the label, you should be able to type your new text directly on it.
Do the same with the Button. Double-click the button in SceneBuilder, and you should be able to modify the button text.
Now you should have a scene graph hierarchy that matches the one above, and the labels and buttons should have text you approve of. Next, we need to fix the layout and hookup the necessary nodes to the controller (that we haven’t created yet.)
Good configuration of elements can turn a so-so layout into a great user experience. Proper padding between elements and between the edges of the windows makes for a layout that is easy on the eyes, and happier users. You’ve been looking at layouts on computers for a long time, so just experiment a bit and you’ll find satisfying combinations of padding, font sizes and such.
Here are the element configurations that I used. Click on each element and make sure the Properties section is expanded on the right hand side to see your current properties configuration.
Here are the properties for the screen elements. You don’t have to match these exactly. Just pick something that looks good to you.
- Title Label … Text Alignment: centered;Font: Futura 14px (Bold)
- Top HBox …Alignment: TOP_LEFT
- Fahrenheit Label … Font: System 13px; Text Alignment: left; Alignment: CENTER_LEFT
- Fahrenheit TextField … Font: System 13px; Alignment: CENTER_LEFT
- Bottom HBox …Alignment: TOP_LEFT
- Celsius Label … Font: System 13px; Text Alignment: left; Alignment: CENTER_LEFT
- Celsius TextField … Font: System 13px; Alignment: CENTER_LEFT
- Button … Font: System 13px; Alignment: CENTER_LEFTSpacing breaks up spaces in visually appealing manner, and makes it easier to find related elements. Here are the layouts for the screen elements. Again, you don’t have to match these exactly.
- Title Label … Margin above and below set to “10”
- Top HBox … Spacing: 10; Pref Width: 200; Pref Height: 100;
- Fahrenheit Label … Pref Width: 75;
- Fahrenheit TextField … Nothing special
- Bottom HBox … Alignment: TOP_LEFT
- Celsius Label … Pref Width: 75;
- Celsius TextField … Nothing special
- Button … Margin above and below set to “10”
Okay. This part is VERY important, and you need to get it right or it will give you all kinds of headaches.
You want access to the events triggered by that Button, and you want access to the two TextFields in your Java code. In JavaFX, your Controller class is going to handle the TextFields and the Button. However, to access them in your JavaFX Controller, you need to give them fx:id‘s, and the Button needs a name for its onAction method.
In the code section on the right of Scene Builder fill in fx:id values for your fahrenheit TextField, celcius TextField, and your convert Button. To work with the sample Controller below, use the values fahrenheitTF, celsiusTF, and convertButton.
Also, give the Button the On Action value of convertClicked. So, you should have entered two values in the code section for your button–one for the fx:id and one for the On Action.
There is one last area to fill out before saving your FXML file to the same folder as your JavaFX’s Main class. If you are a little fatigued at this point, imagine if you had to write all your JavaFX’s FXML by hand. That would be rough.
The last area of Scene Builder that you need to fill in before creating your JavaFX FXML file is the Controller section on the bottom left-hand side.
The one gotcha that always messes things up is naming the Controller class, but not giving the fully qualified package name. If you have just the class name, then when the JRE goes to do all it’s fancy dependency injection you will get an exception stating that the Controller class couldn’t be found.
Finally, here is the code for the ConvertController class.
Not too bad. Bet you’d like a little more explanation, though.
The short and easy explanation is that the method and three fx:id’s you set in your Scene Builder when you were creating your FXML are realized through dependency injection in this custom Controller.
The code for doing the actual conversion to Celsius is in the convertClicked() method. You named that method in Scene Builder, and now you’re using it. Neat.
Note that the initialize() method is called on construction, so put any configuration or initialization code in there.
In summary, there’s a lot to learn when you are creating JavaFX applications that follow MVP or MVC design patterns. JavaFX with FXML is a lot harder than pure Java JavaFX projects. FXML probably isn’t worth it if you are just fulfilling requirements for a homework assignment or making a simple tool. However, if you are creating a complex enterprise-quality application, it will allow the workload to be spread across multiple teams with specialized skills such as UX and UI designers, business logic and data specialists by separating out skill sets. It will also make maintaining the code easier in five to ten years when no one remembers how it was put together.