Posts

JavaFX guide: Go graphical with Java

Aug 17, 2022
Dmitry Chuyko
34.6

Java has a powerful solution for developing rich client applications — JavaFX. Introduced in 2008, it currently matures within the OpenJFX project delivering excellent cross-platform compatibility and modern out-of-the-box solutions for UI. With JavaFX, you can write familiar code in Java to develop desktop applications, without resorting to the complexities of JavaScript or .NET.

In this article, we will explore JavaFX and its features and learn how to write, compile, and deploy JavaFX-based applications.

What is JavaFX?

JavaFX is an open-source platform containing graphics and media tools for developing and deploying rich client applications — programs that store and retrieve data and perform most operations locally, i.e., on a client machine. JavaFX apps run consistently in different environments: desktop, web, mobile, and embedded systems. They can also reference APIs from other Java libraries to use all capabilities of the language and connect to server apps.

Why use JavaFX?

Desktop applications are not a dying technology. There are numerous cases when local/native applications are a preferred choice for users as they provide a more advanced GUI experience, higher performance, and reliability. Use cases for desktop applications include:

  • IDEs
  • Editors
  • Audio and video editors/players
  • Games

In addition, some web and mobile applications have their desktop counterparts, such as Skype, WhatsApp, Telegram, and Slack.

So, desktop development is still a lucrative field for developers, which makes JavaFX a technology worth learning. As per TheirStack data, at least 1,087 companies whose data on the used software stack is available utilize JavaFX (as of February 2025). 

Furthermore, JavaFX goes beyond pure desktop development. For instance, JavaFX apps can be built as native images and used on mobile devices: Gluon offers tools for that purpose, and Liberica Native Image Kit can be used for the fast and convenient transformation of Java apps into native executables.

JavaFX also goes well with embedded devices such as Raspberry Pi. Refer to our guide on running Liberica JDK with JavaFX on this popular single-board computer.

JavaFX vs Swing: key differences

You might be wondering at that point, “If a JDK already contains Swing, why should I bother with JavaFX?”

As mentioned, JavaFX was designed as a substitution for Swing, which lacks many modern features. As a result, it offers many more opportunities for desktop development than Swing. Here is a short comparison of both technologies:

JavaFX

Swing

Used for developing rich client applications with moden user interface

Legacy library for GUI development

Cleaner code base

Many legacy features

Integrated support for MVC

Inconsistent support for MVC

Evolves within the community that regularly introduces enhancements and new features

No new functions are added

Supports both CSS and code-based styling

Only code-based styling

Integrated API for concurrency

No built-in API for concurrency

FXML for declarative layout

No support for declarative layout

Built-in 3D graphics support

Requires additional API for 3D

Support for property binding

No property binding

Comes as a separate bundle starting with JDK 11

Included into JDK by default

Comparative table for Swing and JavaFX

Let’s compare two demo apps written with JavaFX and Swing, which illustrate button customization.

Customizing a button with JavaFX:

public class ScaleTransformationDemo extends Application {

   public static void main(String[] args) {
       launch(args);
   }

   @Override
   public void start(Stage primaryStage) throws Exception {

       Button button = new Button();
       button.setText("Click me!");

       Scale scaleTransformation = new Scale();
       scaleTransformation.setX(3.0);
       scaleTransformation.setY(2.0);
       scaleTransformation.setPivotX(0);
       scaleTransformation.setPivotY(0);
       button.getTransforms().add(scaleTransformation);
       VBox vbox = new VBox(button);
       Scene scene = new Scene(vbox);
       primaryStage.setScene(scene);
       primaryStage.setWidth(512);
       primaryStage.setHeight(256);
       primaryStage.show();

   }

}

In the example above taken from the JavaFX Button tutorial, we added a scale transformation. The customization process with Swing is different.

Customizing a button with Swing:

public class ButtonCustomization extends BasicButtonUI {

   public static void main(String[] args) {

       JFrame f = new JFrame("Button UI Test");
       f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
       JPanel p = new JPanel();
       p.setBackground(Color.white);
       f.setContentPane(p);
       p.setLayout(new FlowLayout(5, 5, 5));
       p.setBorder(new EmptyBorder(10, 10, 10, 10));
       final JButton button = new JButton("Click me!");
       button.setFont(new Font("Calibri", Font.PLAIN, 14));
       button.setBackground(new Color(0x2dce98));
       button.setForeground(Color.white);
       button.setUI(new ButtonCustomization());
       p.add(button);
       f.pack();
       f.setLocation(500, 500);
       f.setVisible(true);

   }

   @Override
   public void installUI(JComponent c) {

       super.installUI(c);
       AbstractButton button = (AbstractButton) c;
       button.setOpaque(false);
       button.setBorder(new EmptyBorder(5, 15, 5, 15));

   }

   @Override
   public void paint(Graphics g, JComponent c) {

       AbstractButton b = (AbstractButton) c;
       paintBackground(g, b, b.getModel().isPressed() ? 2 : 0);
       super.paint(g, c);

   }

   private void paintBackground(Graphics g, JComponent c, int yOffset) {

       Dimension size = c.getSize();
       Graphics2D g2 = (Graphics2D) g;
       g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
       g.setColor(c.getBackground().darker());
       g.fillRoundRect(0, yOffset, size.width, size.height - yOffset, 10, 10);
       g.setColor(c.getBackground());
       g.fillRoundRect(0, yOffset, size.width, size.height + yOffset - 5, 10, 10);

   }
}

To avoid the complexity of code-based styling with Swing, try using CSS supported by JavaFX. Refer to the official JavaFX CSS Reference Guide for details.

Now, if you want to animate the scaling of the JavaFX button, you simply need to use ScaleTransition. The same task won’t be as easy for Swing because it neither has a dedicated class nor concurrency support.

History and Evolution of JavaFX

History

Graphical components have been present in Java since the early age of the language. At first, the focus was made on applets, small applications deployed in web browsers. But as the demand for full-blown desktop apps grew, Java evolved accordingly. First Java versions contained only AWT (Abstract Window Toolkit), a low-level abstract graphic API. Swing APIs introduced in 1998 were built on top of AWT and were aimed at extending the AWT functionality.

JavaFX was released as part of the JDK in 2008. The first version of JavaFX was a scripting language built on top of the JVM. Version 2 of JavaFX already came as a set of Java libraries.

Starting with Java 11, JavaFX was separated from JDK and now evolves within the OpenJFX project.

Support roadmap

Oracle Java 8 still includes JavaFX, which will be supported until March 2025. The release schedule of OpenJFX is based on quarterly updates with security patches and bug fixes. The community provides LTS and minor versions and commercial support by Gluon upon request. BellSoft bundles JavaFX with its own OpenJDK distribution, Liberica JDK (see below).

JavaFX Release

GA date

Latest version

Long-term support

Java 11

September 2018

11.0.26 (January 2025)

Yes

Java 17

September 2021

17.0.14 (January 2025)

Yes

Java 21

September 2023

21.0.6 (January 2025)

Yes

Java 23 (current)

September 2024

23.0.2 (January 2025)

No

Java 24

March 2025 (planned)

Early access

No

Java 25

September 2025 (planned)

Early access

Yes

JavaFX support roadmap

JavaFX comes as a platform-specific SDK, jmods, or a set of artifacts. If you want to use the software with your Java runtime, download the necessary bundle from the developer’s website. We deliver a special flavor of Liberica JDK (Full version) containing LibericaFX — our instance of OpenJFX. Liberica for Embedded also comes with LibericaFX enabling the developers to create GUIs for embedded systems.

JavaFX integrated into the runtime is very convenient:

  • Minimize time and effort spent on installing JavaFX as a separate plugin;
  • Get timely fixes together with runtime updates;
  • Receive first-hand support from our engineers within the scope of JDK support.

End of Life for JavaFX support on Oracle Java SE 8

Support for JavaFX on Java SE 8 ends in March 2025 as per Oracle Support Roadmap. It means that Oracle will no longer provide Oracle Java 8 builds with JavaFX. If you have been using Oracle Java SE 8 with JavaFX, you will have to either upgrade to a newer JDK version and request support for JavaFX or migrate to Liberica JDK 8, which enjoys extended long-term support until March 2032, including JavaFX support. You can get and use Liberica JDK 8 Full with Java FX at no cost. Or from SDKMAN:

sdk install 8.0.432.fx-librca

Key advantages of JavaFX

There are several reasons to use JavaFX for developing GUI applications:

  • JavaFX enables the developers to write clear, manageable code in Java, which is easy to update or debug. Writing code for desktop applications in JavaScript is far more complicated, and cross-platform compatibility of .NET apps is inconsistent.
  • There is a short learning curve for Java developers or programmers who have already worked with Java-like technologies.
  • JavaFX includes all necessary libraries for desktop development and supports CSS styling, FXML, and multithreading. It provides many functions out-of-the-box (see the section below), and as a bonus, it has a convenient JavaFX Scene Builder, a visual layout tool for designing UIs without coding.
  • JavaFX is open source and part of an active community. Updates with security patches and bug fixes come out regularly, and even when Oracle ceases JavaFX support as part of Java 8 in 2025, the technology will still be developed by the community within the OpenJFX project.
  • Thanks to the support for native image technology in Liberica NIK 21.3 and up, the JavaFX app can be bundled and deployed as native executables that take less space on a disk and start up almost instantly.

How to install JavaFX

As JavaFX evolves as a standalone project, there are two ways of getting it: you can download JavaFX separately from the OpenJFX website or get JDK builds bundled with JavaFX. BellSoft is one of few OpenJDK vendors that provide JDK binaries with JavaFX. You can get Liberica JDK Full version, which is a version with JavaFX, from Liberica JDK Download Center, or get Liberica JDK with JavaFX via a package manager. For instance, in SDKMAN they have an 'fx' tag. So, for instance, to get Liberica JDK 23 with JavaFX, run

sdk install 23.fx-librca

JavaFX architecture and core components

JavaFX components

JavaFX has an extensive range of features for developing GUIs: tables, buttons, trees, menus, and many more. It also supports CSS, 2D and 3D Graphics, and WebView. 

Key JavaFX components:

  • Stage is a window in a JavaFX application. When the application starts, it creates a root Stage object, which is the main window of the app. But you can create multiple stages if your app has multiple windows.
  • Scene is a component where you add GUI components. A Scene object is set on the Stage.
  • Node is a superclass of all components added to the Scene Graph. Stage and Scene make the Scene Graph visible, but only Node elements added to the Scene are considered part of the Stage Graph. 
  • FXML is an XML-based markup language for creating a layout of JavaFX apps. FXML helps you to separate the layout code from the application code, making the latter more concise. 

JavaFX features with examples of subcomponents for better understanding are listed below:

  • Core: FXML, Stage, Scene, etc.
  • Layout: HBox, VBox, Border Pane, Text Flow, Flow Panel, etc.
  • UI controls: Label, Button, TextField, MenuBar, etc.
  • Container controls: Accordion, TablePane, etc.
  • Web: WebView, etc.
  • Charts: PieChart, BarChart, etc.
  • Other tools: fonts, animation, effects, etc.

JavaFX APIs

JavaFX public APIs include all classes required for building a GUI application. The most important ones are listed below:

  • javafx.scene provides a set of core classes for the JavaFX Scene Graph API, which is the foundation for JavaFX applications. There are several subpackages with classes for different purposes such as working with texts, images, media, keyboard and mouse input events handling, and many more. 
  • javafx.animation includes classes for adding and handling transition-based animations.
  • javafx.css provides classes for working with styles using CSS.
  • javafx.fxml includes classes for loading objects from the markup file.
  • javafx.event provides classes for handling JavaFX events.
  • javafx.geometry contains classes for working with 2D objects.
  • javafx.stage provides container classes for the JavaFX content. 

JavaFX tools and libraries

Numerous libraries, frameworks, and third-party resources enhance the experience of working with JavaFX. The libraries enable the developers to create beautiful apps with more concise code, and frameworks add extra functionality.

Let’s discuss some of them briefly to illustrate the capabilities of the JavaFX platform you can make use of.

  • MigLayout is an open-source library that aids in developing and managing layouts. It provides tools for multiple layout types: flowing, grip-based, docking, etc. The code written in MigLayout is very concise and represents the appearance of a layout clearly.
  • Ikonli is a library providing numerous icon packs for different icons and making it possible to customize and style icons.
  • RichTextFX offers tools for creating rich text editors and code editors with syntax highlighting and various fonts.
  • JacpFX is a framework that helps to structure the app with loosely coupled, reusable JavaFX components. The task execution can be separated from UI changes in the client application, thus enabling the developers to avoid the multithreading issues. JavaFX functionalities include message-bus communication between components and asynchronous processes support.
  • Skija provides Java bindings for Skia, an open-source library for developing rich 2D graphics. It is highly performant, easy to use, and robust, with support for color spaces, modern typography and GPU backends, and highly-optimized GPU rendering.

Creating a user interface with JavaFX

Scene Builder

The easiest way to start building a UI with JavaFX is to use a Scene Builder. It has a convenient drag-and-drop interface where you can create a layout for your application and export it as an FXML file.

Download, install, and open the application.

Scene Builder interface

On the left, you can see the Library with the groups of UI components: containers with panes and boxes, controls with buttons, text, labels, etc, and so on. In the middle on the left, there is a Document section showing the hierarchy of elements we will add to the Scene Graph, and at the bottom, there is a Controller where you can specify the Java Controller class for this window.

On the right, there is the Inspector where you can customize each element.

Layout

Let’s start with a layout. Some important containers:

  • HBox and VBox are the components that place all their child nodes in a horizontal or a vertical row accordingly.
  • BorderPane is a pane that arranges the child nodes in the top, left, right, bottom and center positions.
  • GridPane places the child nodes in a grid.
  • FlowPane lays out the child nodes vertically or horizontally and can wrap them at their width or height accordingly. 
  • TilePane lays out the child nodes in a grid with equally sized cells.

Let’s use BorderPane. Choose the component in the Containers section and drag it to the center of the canvas. This is going to be our starting point. You can customize the element. On the right, there are three sections: Properties, Layout, and Code.

We will change the background color. Select Properties, Style, and paste -fx-background-color to the left cell and #E0F6FD to the right. Also, go to Layout and set Padding on the bottom to 10.

Main UI components

There are numerous UI components you can add to a JavaFX application, including:

  • Text elements: Label, TextArea, TextField;
  • Buttons: Button, CheckBox, RadioButton;
  • Charts and diagrams: PieChart, BarChart;
  • Sliders and bars: MenuBar, ScrollBar, Slider.

In Controls, choose TextArea and drag it to the top of the BorderPane. Go to Code and enter text in fx:id. 

Choose Label in Controls and drag it to the center of the pane. Go to Code and enter dataLabel in fx:id.

Also in Controls, choose Button and drag it to the bottom of the pane. Go to Properties and name the button Say hello! 

You can play around with colors, fonts, etc. After that, go to Code and enter helloButton in fx:id and sayHello in onAction. These fields are required to tie the FXML file to the code of our application.

This is the resulting window.

Finally, in the Controller section at the bottom, enter the name of the Controller you will use in your app. In my case, it was dev.cat.HelloController.

Save the file and let’s move on to the IDE.

Create a JavaFX project

The easiest way to create a JavaFX project is to install an OpenJDK distribution bundled with JavaFX. In this case, you can create a project without adding additional dependencies for FX.

Download Liberica JDK Full, which includes LibericaFX, an instance of OpenJFX. You can also get the binaries from your favorite package manager. For instance, with SDKMAN:

sdk install 23.fx-librca

Install Liberica JDK, then create a new Java project in your IDE. 

Creating JavaFX project

Integrate FXML file in your JavaFX application

Place the .fxml file into the resources directory.

First of all, we need to make our Main application class extend Application from the javafx.application package, implement its method start(), and call the method launch() from the main method:

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {

    }

    public static void main(String[] args) {
        launch(args);
    }

}

Now, we need to load the FXML file in the start() method. For that purpose, create an instance of FXMLLoader and set the location of the FXML file using its setLocation() method. 

FXMLLoader loader = new FXMLLoader();
loader.setLocation(new URI("file:src/main/resources/home.fxml").toURL());

After that, create a root node and load the file:

BorderPane pane = loader.load();

Finally, create a Scene, passing the root node as the parameter, and set the Scene on the Stage. The whole body of the method should look like this:

@Override
public void start(Stage primaryStage) throws Exception {

        FXMLLoader loader = new FXMLLoader();
        loader.setLocation(new URL("file:src/main/resources/home.fxml"));
        BorderPane pane = loader.load();

        Scene scene = new Scene(pane);
        primaryStage.setScene(scene);
        primaryStage.show();

}

It’s time to connect the FXML file to the Controller. Create a new Java class, for instance, HelloController. FXML files can be connected to Java fields and methods using the @FXML annotation.

So, as we tied the button to the sayHello method, let’s create it in the Controller and annotate this method with @FXML. In addition, we need two fields, TextArea and Label, also annotated with @FXML. Make sure that the names of the variables are the same as fx:id field in the FXML file.

public class HelloController implements Initializable {

    @FXML
    private TextArea text;

    @FXML
    private Label dataLabel;

    @FXML
    void sayHello() {

    }
    @Override
    public void initialize(URL location, ResourceBundle resources) {
        
    }

Specify the name of the Controller in the FXML file if you haven’t done it in Scene Builder:

<BorderPane xmlns="http://javafx.com/javafx/23.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="dev.cat.HelloController">

The FXML file is now tied to our application. But the app doesn’t do anything useful yet, let’s fix that.

Change the text of the Label using StringProperty

It is possible to set a text or even an image of a Label that will be displayed when you run the application. For our simple scenario, we could simply use the setText() method of a Label class. 

However, we will implement another approach using the StringProperty, whose values can be observed or changed and displayed dynamically based on the user input.

For that purpose, we will need to add and initialize the StringProperty field in the Controller:

StringProperty name = new SimpleStringProperty();

In the initialize() method, we need to bind the value of Label to StringProperty:

@Override
public void initialize(URL location, ResourceBundle resources) {
dataLabel.textProperty().bind(name);
}

Finally, in the sayHello() method, use the setMethod() of StringProperty to change the value of name to user input that we can extract from TextArea with getText()

@FXML
void sayHello() {
        name.setValue("Hello, " + text.getText() + "!");
}

The whole body of the Controller class:

public class HelloController implements Initializable {

    @FXML
    private TextArea text;

    @FXML
    private Label dataLabel;

    StringProperty name = new SimpleStringProperty();

    @FXML
    void sayHello() {
        name.setValue("Hello, " + text.getText() + "!");
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        dataLabel.textProperty().bind(name);

    }

You can now run the application and check that everything works correctly.

How to switch scenes in JavaFX

Our tiny application works with one scene, but in some cases, it won’t be enough. So, how do we switch scenes?

First of all, you need to create a new FXML file and add it to the project. Then, you create a Controller class for this file and connect the business logic to the interface like we did before.

There are several ways of switching scenes. Here’s one of them for the scenario when you need to change the scene as soon as the user pushes the button. 

First, create a static Stage field in the Main class and tie it to the primaryStage in the start() method:

   private static Stage stage;

    @Override
    public void start(Stage primaryStage) throws Exception {

        stage = primaryStage;

        FXMLLoader loader = new FXMLLoader();
        loader.setLocation(new URI("file:src/main/resources/home.fxml").toURL());
        BorderPane pane = loader.load();
        Scene scene = new Scene(pane);
        primaryStage.setScene(scene);
        primaryStage.show();

    }

Second, create a static method switchToSecondScene() in the Main class. You can use any sensible name for the method, this one here is just an example. In this method, create an instance of FXMLLoader and set the location of the second FXML file. Then, create a new Scene and add it to the Stage:

public static void switchToSecondScene() {

        FXMLLoader loader = new FXMLLoader();
        loader.setLocation(new URI("file:src/main/resources/second-view.fxml").toURL());
        BorderPane pane = loader.load();

        Scene sceneTwo = new Scene(pane);
        stage.setScene(sceneTwo);
        stage.show();
}

Finally, call the switchToSecondScene() method in the Controller connected to the first FXML file. If the scene changes upon button action, add the call to the button handling method:

@FXML
void switchScene() throws Exception {
        Main.switchToSecondScene();
}

You now have two scenes in your JavaFX application, but what if you need to pass data between two Controllers?

You can accomplish this task in four steps:

Add a parameter to the switchToSecondScene() method that specifies the data you want to pass. For instance, a String:

public static void switchToSecondScene(String text) { }

Extract the data in the first Controller and pass it to the method:

   @FXML
    private TextArea text;
   
    @FXML
    void switchScene() throws Exception {
        Main.switchToSecondScene(text.getText());

    }

Define a method for saving the data in the second Controller:

   public void saveData(String text) {
        //saving logic
    }

Get an instance of the second Controller in the switchToSecondScene() method by calling loader.getController() and call the Controller method for saving the data:

  public static void switchToSecondScene(String text) {

        FXMLLoader loader = new FXMLLoader();
        loader.setLocation(new URI("file:src/main/resources/second-view.fxml").toURL());
        BorderPane pane = loader.load();

       SecondController controller = loader.getController();
        controller.saveData(text);

        Scene sceneTwo = new Scene(pane);
        stage.setScene(sceneTwo);
        stage.show();

    }

Animations in JavavFX

Animation is the process of changing the position of objects or applying transformations to create an illusion of movement.

We can add animations to JavaFX applications. The javafx.animation package includes classes for applying various transitions to the objects. These transitions can be roughly classified as

  • Simple transitions represented by FadeTransition, ScaleTransition, RotateTransition:
    • The FadeTransition class is used to change the opacity of the JavaFX node over time.
    • ScaleTransition enables scaling a node over time.
    • RotateTransition enables rotating a node by a specified axis over time.
  • Complex transitions represented by SequentialTransition and ParallelTransition:
    • SequentialTransition plays a list of animations in sequential order.
    • ParallelTransition plays a list of animations in parallel.
  • Animation by trajectory is made possible with PathTransition, which moves a node over specified path over time.
  • Custom transitions can be created using the Timeline class. You can add KeyFrames to the timeline specifying the animation and its duration.

Take a look at an example of animating an object in JavaFX. Let’s return to our minimalistic application we created above. Suppose we want to animate a Button and add ScaleTransition to enlarge the button on mouse hover.

Add the button field and annotate it with @FXML. In the initialize() method, create a ScaleTransition instance:

public class HelloController implements Initializable {

    @FXML
    private Button helloButton;

    @Override
    public void initialize(URL location, ResourceBundle resources) {

        ScaleTransition scale = new ScaleTransition(Duration.seconds(1), helloButton);
        scale.setByX(0.5);
        scale.setByY(0.5);
        scale.setCycleCount(2);
        scale.setAutoReverse(true);


        helloButton.setOnMouseEntered(e -> scale.play());

    }

The code in the initialize() method

  • Creates a new ScaleTransition, sets the duration and the object we want to apply this transition to;
  • Sets the new size of a button with setByX() and setByY();
  • Returns the button to the normal size after playing the animation with setAutoReverse(true);
  • Defines when the animation will be played, in our case, on mouse hover with setOnMouseEntered().

Event handling in JavaFX

The application needs to react to the user's actions. In JavaFX, when the user interacts with the application nodes, for instance, pushes a button, an event is triggered. This event is handled by the application code.

The javafx.event package includes classes that can be used to handle various events. Some of the key JavaFX events are: 

  • MouseEvent (MouseClicked, MouseEntered, MouseExited) is an event triggered when the mouse is used.
  • KeyEvent (KeyPressed, KeyReleased, KeyTyped) is an event triggered when the keystroke is detected on a node.
  • WindowEvent is an event triggered when window-related actions happen like showing or hiding a window.
  • DragEvent is an event triggered when the user drags and drops items in the interface.

In the example above, when we added action to our button, we used an event onMouseEntered meaning that when the user hovers a mouse over a button, an animation is played.

helloButton.setOnMouseEntered(e -> scale.play());

You can also use the EventFilter when you need to evaluate the event before it is processed. For instance, we can disable exiting the application with the ESCAPE key:

scene.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
    if (event.getCode() == KeyCode.ESCAPE) {
        System.out.println("Escape key disabled");
        event.consume();
    }
});

You can also create custom events by extending the Event class:

public class CustomEvent extends Event {
    
    public CustomEvent(EventType<? extends Event> eventType) {
        super(eventType);
    }

//business logic here

}

How to compile and deploy JavaFX applications

There are two ways of building JavaFX applications. You can create a standard JAR file or a native image.

To build a JAR file, add the following plugin to your pom.xml file:

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>dev.cat.LotteryApp</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>

You may also have to specify the start class in the properties section:

   <properties>
        <maven.compiler.source>23</maven.compiler.source>
        <maven.compiler.target>23</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <start-class>com.fxdemo.Main</start-class>
    </properties>

After that, you can create a JAR file with

mvn clean package

JavaFX applications can also be turned into native images that start up almost instantly. But these builds are OS and platform-specific, meaning that if you compile the app on AArch64 mac, it won’t run on x86_64 Linux. The solution is to build the native image further down the CI/CD pipeline, for instance, using GitHub Actions.

Refer to these guides on building JavaFX native images and using GraalVM Native Image with GitHub Actions for more information.

Conclusion

JavaFX is still commonly used in enterprise development. This technology is actively developed by the OpenJFX community, and enterprise support is provided by several companies, including BellSoft.

Starting with JavaFX is no challenge, and FXML integration makes desktop development with Java even more convenient.

For more guides on JavaFX, refer to the official OpenJFX documentation.

 

Subcribe to our newsletter

figure

Read the industry news, receive solutions to your problems, and find the ways to save money.

Further reading