Skip to main content
  1. JavaFX/
  2. Example Projects/

How to Build a JavaFX Application That Does Something

11 mins·
Table of Contents

Introduction
#

People seem to get stuck when it comes to turning their JavaFX application into something useful; something that connects to the outside world, or saves and retrieves its data using a database, or interacts with some other application. I’ve seen this question asked from both directions:

How do I connect my JavaFX application to an SQL Database? I have a screen but I need to be able to save and read information.

or:

I have an application that does this interesting thing, but I’d like to add a JavaFX front end onto it. How do I do this?

These are reasonable questions. How do you do this:

Answer: Use a Standard Framework
#

The simple answer is to use a standard framework that will allow you to split your application into two parts. One part is the GUI, and the other is whatever your application actually “does”. Personally, I prefer Model-View-Controller, since it works really well with JavaFX as a Reactive environment. But that just describes the GUI part of your application.

At some point, you have to connect your GUI with the part of your application that does the work - which we’ll call the “domain” code. You need an interface that allows the GUI and the domain code to interact in a particular way. I call that the “Interactor”.

Now your application has three parts:

  • The GUI (Model, View and Controller)
  • The Interactor
  • The Domain Code
MVCI

Why Do This?
#

This first time I was shown an MVC structure I struggled to understand what the benefit was. How does this make it any easier to build an application? I think that there are two key advantages to using this framework.

First, it makes your programming easier to manage because it reduces coupling. Coupling occurs when the parts of application have too many dependencies on each other. It can be insidious, building up a little at a time, until it becomes impossible to change one part of your application because then you have to change something else, and then something else, and so on. Using a framework like MVC-I forces you to keep those pieces apart from each other, right from the start, and gives you clear rules about how much each part is allowed to know about the other parts. In the end, your application structure is much easier to understand.

Secondly, it takes away the blank page syndrome. You’re not starting from zero, and even if it feels a little bit like, “paint by numbers”, at the start it makes very easy to get a bare skeleton up and running - sometimes in just minutes.

The Interactor
#

The heart of the question of, “How do I make my JavaFX application do something?”, really comes down to the role of the Interactor.

The Interactor is the only part of your system which has any knowledge about the other two parts. It’s the place where domain objects and the Model can exist together, and you can have code which is aware of both of them.

The Interactor is also the place where your specific application logic goes. While it has knowledge of the domain, its job is to support whatever function within the application that the MVC part of the framework supplies. It’s a part of a process that has the GUI as one end-point, and some “external” domain at the other end, and it contains all of the rules and logic that make the process work.

Example Application - A Simple Weather App
#

Here we’re going to look at a simple application that has all of the components that you’ll need:

  • A Reactive MVC GUI
  • Application logic in an Interactor
  • A weather fetching service
  • A domain object
  • An external API

Before we go any further, let’s see what it looks like when it’s running:

Screen Shot

It’s pretty simple. You pick a city from a small list in the ComboBox then click “Get Weather” and it retrieves the information. There’s only 3 pieces of data: the temperature, a description of the conditions, and an image associated with the conditions.

All of this information comes from a web API from openweathermap.org.

API Token
#

If you want to run this application, you’ll need an API Token from openweathermap.org. You can get one for free from their site, and the link is on the “Pricing” page, under the “Free” column. You’ll probably be redirected to a login/sign-up page before you get there.

Get An API Token

When you get a token (it’s just a string of characters), you’ll need to copy it into a resource file in the project. Under “resources”, create a directory called “data”, and then create a file in it called “api.data”. Then just copy your token into it on the first line. Check the constructor of WeatherFetcher in the source code if any of this is unclear.

The application doesn’t have particularly robust error handling, but if it cannot find the token it will give you a message that it had a problem. If the token is invalid, you just won’t get any weather reports in the GUI.

Application Components
#

You should take a look at the project on GitHub. It’s not very big, and I’m only going to include a small part of the code in this article.

GitHub Project

The ViewBuilder
#

The ViewBuilder is an implementation of the JavaFX Builder utility interface, returning a Region. Using a Builder here is better than the only other real alternative, which would be to extend one of the layout classes, like BorderPane, and configure it through its constructor.

In this case, the Region returned is a BorderPane. The centre of the BorderPane is an HBox holding the weather image, and a VBox that has the city name, and a GridPane with the weather information. The bottom of the BorderPane is an HBox with the city selection ComboBox and the Button which triggers the data load.

All of the styling in the View is done through CSS, which is included in the project.

There are a couple of static convenience classes that instantiate and configure some of the Nodes in the View. This helps to keep the ViewBuilder concerned with layout only, keeps it from getting clogged up with JavaFX boilerplate.

To allow the Button in the View to actually do something, the ViewBuilder is supplied a Consumer<Runnable> by the Controller through a constructor parameter. This is really just a callback containing a callback. We’ll look at this a little later.

Finally, the Model is passed to the ViewBuilder through its constructor, and the Model properties are connected to the View elements as they are instantiated. From this point on, any changes in the Model will be automatically reflected in the View.

The Controller
#

The Controller is responsible for instantiating the other MVC components and the Interactor. In this respect it’s the “centre” of the application. The Main class for the application instantiates the Controller in order to bootstrap the GUI, and then calls its getView() method to get the root for the Scene.

The Controller is also responsible for handling FXAT threading. This is important in this kind of application, because virtually anything that needs to talk to the domain code will need to run off the FXAT, and then the effects of that domain code need to be applied back to the model by code running on the FXAT. Usually, this needs to be coordinated with both the View and the Interactor, so the Controller is the right place for that to happen.

The WeatherFetcher
#

This is the “domain code” of this application. It’s small, just a single class that is able to perform a couple of HTTP “GET” transactions with openweathermap.org, use some JSON parsing to extract the information and package up the results in a domain object - WeatherData.

It essentially becomes a service, wrapping the calls to openweathermap.org in it’s own logic and the bundling the response into a locally defined domain object.

The Interactor
#

This is where the “application logic” resides. The Interactor is instantiated by the Controller, and it is passed the Model as a parameter in its constructor. It has two methods, checkWeather() and updateWeatherModel(). The checkWeather() method invokes a method in the WeatherFetcher, and then stores the WeatherData object that is returned in a private field. The updateWeatherModel() method takes the data stored in that WeatherData object and puts it into the Model.

Although the Interactor has no knowledge, and no logic, that is aware of the FXAT or any other threading issues, the design is such that checkWeather() will be called on a background thread, while updateWeatherModel() will be called on the FXAT.

Invoking the Weather Fetch
#

Let’s look at the View first, and the set-up for the Button:

private final Consumer<Runnable> weatherFetcher;
        .
        .
        .
Button button = new Button("Get Weather");
button.setOnAction(evt -> {
    button.setDisable(true);
    fetchWeather.accept(() -> {
        button.setDisable(false);
    });
});

You can see that weatherFetcher is a Consumer<Runnable>. So it’s a piece of code that is going to accept another piece of code as a parameter. Essentially, it’s a callback.

Why do this?

When the Button is clicked, the first thing that we need to do is to disable it, so that it cannot be clicked again while the fetch is happening. But then we need to re-enable it when it’s all done. The problem that we have is that there is no mechanism that allows us to “wait” for the fetch to complete, because that would hang our GUI. So what we have to do is invoke the fetch, and then give the fetcher (whatever it may be) some code to execute when the fetch is completed.

In this case, that code just re-enables the Button.

Now, let’s look at the what weatherFetcher does. It’s defined in the Controller:

private void fetchWeather(Runnable postFetchGuiStuff) {
    Task<Void> fetchTask = new Task<>() {
        @Override
        protected Void call() {
            interactor.checkWeather();
            return null;
        }
    };
    fetchTask.setOnSucceeded(evt -> {
        interactor.updateWeatherModel();
        postFetchGuiStuff.run();
    });
    Thread fetchThread = new Thread(fetchTask);
    fetchThread.start();
}

Here we are defining a JavaFX element called a Task. A Task is JavaFX class which is designed to facilitate running code on a background thread and then get back on the FXAT. It’s possible to have a Task return a result, but in this case we don’t need it to, as the Interactor is going to store the results in a field.

The next thing to note is the call to setOnSucceeded(). Whenever you see a method called setOn...() in JavaFX, that means that you’re going to be passing it an EventHandler. The most important thing about this is that EventHandlers always run on the FXAT. The EventHandler passed to setOnSucceeded() is executed when the Task ends in any way other than throwing an exception. So this call to setOnSucceeded() tells us how the Controller is going to get the processing back on the FXAT after it’s done running on the background thread.

In this case, we want to do two things on the FXAT once the background thread has completed. We want the Interactor to update the Model with the data it just fetched, and then we want to run that code that came from the Button - the one that re-enables the Button.

Finally, the Controller initializes a new Thread for the Task, and starts it.

You should be clear that fetchWeather() itself runs on the FXAT. This means that the Task is configured on the FXAT, the Thread is initiated and started from the FXAT, but everything in fetchTask.call() is executed on that new Thread.

Just to be more explicit, all of this means that interactor.checkWeather() is run in a background thread, while interactor.updateWeatherModel() is run on the FXAT.

Just to be even more explicit: This is the only place in our application code that has any knowledge about the FXAT and the only place where threads are addressed at all. This is one of the main responsibilities of the Controller.

Conclusion
#

This is about as simple as you can make an application that has a domain layer but yet it has all of the basic components that you need to deal with. You could clone this project and start changing the names of the classes and the methods and it probably wouldn’t be a bad start.

Yeah, But What If I Really Want To Use FXML?
#

I wouldn’t. It doesn’t do anything for you. However, if you must…

Remember that the FXML Controller is NOT an MVC Controller. You need to think of the FXML, FXML Loader and FXML Controller together as the “View” in MVC. And for that matter, the FXML file isn’t a Model either, even though it feels like data.

What you’ll need to do is to create an MVC Controller that instantiates the View by calling the FXML Loader and then passing your Model into the FXML Controller to create the Bindings that connect it to the Nodes in the GUI. If you can do that, then the rest of your application structure should be just as described in this article.

But once again, I wouldn’t bother with FXML.

Related

Demystifying PseudoClasses in JavaFX

11 mins
Pseudo Classes are the best way to handle on/off state changes in a Node in JavaFX. But it’s very badly explained in the JavaDocs and hard to understand. This article should clear that up.

Hangman in JavaFX

13 mins
How much code does it take to build a complete Hangman game in JavaFX? It turns out … Not much!

Implementing MVC in JavaFX

14 mins
Model-View-Controller is generally accepted as a good way to structure an application with a user interface. While JavaFX contains all of the classes needed to implement MVC in a natural and seamless way, it doesn’t seem to be widely documented and there’s little evidence on the Web that many people have figured out how to do it properly. The fact that JavaFX supports Reactive programming makes a big difference to how you should implement MVC.

Wordle in Kotlin JavaFX

16 mins
The original Wordle is JavaScript in a browser, here’s an implementation of it in Reactive JavaFX written in Kotlin.

MineSweeper in JavaFX

19 mins
MineSweeper! Everyone’s favourite time-waster Windows game. Implemented in JavaFX showing how the reactive nature of JavaFX can be used with MVC to create a game.

How to Write a JavaFX Screen without FXML & Scene Builder

17 mins
Way, way back in 2014 when I started learning JavaFX, I tried using Scene Builder and FXML and found it to be an amazing waste of time and effort. One of the best decisions I ever made was to abandon it early on, and just code screens by hand. I advise everyone else to do the same.

TextFields and TextFormatter - Part 1

8 mins
An introduction to TextFormatter, showing you how to integrate it into a TextField and how to use it to convert the input from String to some other kind of value. Then we’ll look at how to add a filter to prevent the user from entering invalid data.

TextFields and TextFormatter - Part 2

11 mins
A more in-depth look into how to build a TextFormatter that can be used to turn a TextField into sophisticated input field. We’ll look at designing a TextFormatter that is tailored to handle fixed place decimal input, using the decimal point itself as a control to toggle between the ordinal and mantissa of the number.

Part 5 - Application Framework

3 mins
Building an application that “does something” means adopting a framework that works well with JavaFX. Here we build the skeleton of the Model-View-Controller-Interactor framework that we’re going to use for our CRUD application.