Guides for SE student projects »

JavaFX tutorial part 1 – Introduction

Lifecycle of a JavaFX application

Imagine yourself as a director of a play. First you provision the props that you will feature in your play. These can be hand props for your actors to interact with or even set dressings just to liven up the background. You then decide where to layout the props for every scene. With a proper script in hand, you can finally approach a theatre and request for a stage. There on, it’s just a matter of pulling the curtains on your masterpiece.

A JavaFX application is like a play you are directing. Instead of creating props, you create Nodes (Nodes are the fundamental building blocks of a JavaFX application), and place them onto a Scene (a scene is a graph of Nodes). Then, you set your Scene on a Stage provided by JavaFX. When you call Stage#show() method, JavaFX renders a window with your Stage on it.

Setting up Java FX

Note: this tutorial assumes you will be using Gradle to manage dependencies of your project.

Update your build.gradle to include the following lines:

repositories {
    mavenCentral()
}

dependencies {
    String javaFxVersion = '17.0.7'

    implementation group: 'org.openjfx', name: 'javafx-base', version: javaFxVersion, classifier: 'win'
    implementation group: 'org.openjfx', name: 'javafx-base', version: javaFxVersion, classifier: 'mac'
    implementation group: 'org.openjfx', name: 'javafx-base', version: javaFxVersion, classifier: 'linux'
    implementation group: 'org.openjfx', name: 'javafx-controls', version: javaFxVersion, classifier: 'win'
    implementation group: 'org.openjfx', name: 'javafx-controls', version: javaFxVersion, classifier: 'mac'
    implementation group: 'org.openjfx', name: 'javafx-controls', version: javaFxVersion, classifier: 'linux'
    implementation group: 'org.openjfx', name: 'javafx-fxml', version: javaFxVersion, classifier: 'win'
    implementation group: 'org.openjfx', name: 'javafx-fxml', version: javaFxVersion, classifier: 'mac'
    implementation group: 'org.openjfx', name: 'javafx-fxml', version: javaFxVersion, classifier: 'linux'
    implementation group: 'org.openjfx', name: 'javafx-graphics', version: javaFxVersion, classifier: 'win'
    implementation group: 'org.openjfx', name: 'javafx-graphics', version: javaFxVersion, classifier: 'mac'
    implementation group: 'org.openjfx', name: 'javafx-graphics', version: javaFxVersion, classifier: 'linux'
}

After updating the build.gradle file, remember to reload the Gradle dependencies using your IDE UI, or by running the command ./gradlew clean build. If using an IDE, you can restart the IDE for good measure.

Writing your first program

As customary, let’s start off with a simple “Hello World” program. Let's say you have a class named Duke that you want make a GUI. First, modify the Duke class to extend javafx.application.Application. This requires you to override the Application#start() method and provide a concrete implementation. Notice that the method signature for Application#start() has a parameter Stage. This is the primary stage that JavaFX provides.

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.stage.Stage;

public class Duke extends Application {

    // ...

    @Override
    public void start(Stage stage) {
        Label helloWorld = new Label("Hello World!"); // Creating a new Label control
        Scene scene = new Scene(helloWorld); // Setting the scene to be our Label

        stage.setScene(scene); // Setting the stage to show our screen
        stage.show(); // Render the stage.
    }
}

Note how we have created a Label to contain the text that we want to show. We then create the Scene and set its content. Finally, we set the stage and show it.

Next, we create another Java class, Launcher, as an entry point to our application. The Launcher class is reproduced below in its entirety.

import javafx.application.Application;

/**
 * A launcher class to workaround classpath issues.
 */
public class Launcher {
    public static void main(String[] args) {
        Application.launch(Duke.class, args);
    }
}

JavaFX creates the Application instance by calling the no-argument constructor. So, you need to define a no-argument constructor in the Duke class (i.e., the Application subclass you use) if you don't have one already e.g.,

//...

public class Duke extends Application {

    public Duke() {
        // ...
    }

    // ...
}

Now, run Launcher and you should see something like this:

Hello World

The following warning issued by Java runtime can be ignored. This warning appears when you use a later JavaFX version (e.g., 17) with a JDK version that doesn't support the modules feature yet (e.g., Java 11).

WARNING: Unsupported JavaFX configuration: classes were loaded from 'unnamed module @...

Congratulations! You have created your first GUI application!

Exercises

  1. We mentioned that Nodes are the fundamental building blocks of JavaFX and used a Label as our root node in the HelloWorld application.

    1. What are some of the other types of Nodes?
    2. How does JavaFX group them?
  2. Nodes can be interacted with like Plain Old Java Objects (POJO).

    1. What properties of a Label can you change programmatically?
    2. Try changing the Label to have a font of Arial at size 50.
  3. You’ve learnt that a Stage can be thought of as a window.

    1. Can you have more than one Stage an application?
    2. Try creating another stage and showing it! What happens?

ToC | What's next? JavaFX tutorial part 2 - Creating a GUI for Duke


Authors:

  • Initial Version: Jeffry Lum