Skip to Content

JavaFX: A Newer Java UI Framework

For a long time Java Swing has been the UI library/framework that was used to create GUI (Graphical User Interface) programs in Java. But in recent years, a new framework called JavaFX has come along, and it has become popular. Some features of JavaFX that are nice are: using HTML and CSS to style UI features rather than raw Java code, and built-in 2D and 3D graphics, and sound (I think).

There is also a UI design tool called SceneBuilder which will let you drag+drop your UI together, and then will generate the relevant code.

However using an IDE, and SceneBuilder, it may not always be obvious how to package and run your code outside of the IDE. Real users are not going to run your program in an IDE, so learning how to run it outside is a must!

Below is a Hello example of a JavaFX program that has the raw code to start up and read and apply an FXML style.

The official tutorials for JavaFX and Swing can be useful (then click on “Tutorials”)!

This curated list of JavaFX resources may be useful.

The bottom of this page has links to some of my own JavaFX examples.

Compiling and Running under Ubuntu Linux (and others, maybe)

Newer versions of OpenJDK do not have OpenJFX included, it seems. I used to be able to compile this JavaFX without any special options, but no longer. The compile and run commands I got to work on my Linux computer are:

javac --module-path /usr/share/openjfx/lib --add-modules javafx.controls,javafx.fxml Hello.java
java --module-path /usr/share/openjfx/lib --add-modules javafx.controls,javafx.fxml Hello

This was after I figured out where the JFX files were installed, by doing the command

find /usr -name 'javafx.controls*'

note that you have to have those options both on the compile and run commands.

Hello.java Code

The following code is in the file Hello.java:

//
// Loading and starting an FXML-based JavaFX program 
//
// helpful sites:
// https://docs.oracle.com/javase/8/javafx/api/javafx/fxml/doc-files/introduction_to_fxml.html
// https://jenkov.com/tutorials/javafx/fxml.html#specifiying-controller-class-in-fxml
// https://docs.oracle.com/javafx/2/api/javafx/fxml/doc-files/introduction_to_fxml.html#controllers
// https://docs.oracle.com/javafx/2/api/javafx/fxml/FXMLLoader.html
// https://docs.oracle.com/javafx/2/api/javafx/application/Application.html
//

// TODO: clean up these imports, most not needed
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import javafx.event.Event;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.fxml.FXMLLoader;

public class Hello extends Application
{

private Pane pane=null;
private Scene scene=null;

@FXML
public void mybuttonAction(Event e)
{
   System.out.println("Button clicked! ("+e+")");
}

@FXML
public void menuFileClose(Event e)
{
   System.out.println("File->Close! ("+e+")");
   javafx.application.Platform.exit();
}

@FXML
public void menuHelpAbout(Event e)
{
   System.out.println("Help->About! ("+e+")");
}

@Override
public void init()
{
   // API docs say "NOTE: This method is not called on the JavaFX
   // Application Thread. An application must not construct a Scene 
   // or a Stage in this method. An application may construct other 
   // JavaFX objects in this method. 
   FXMLLoader loader = new FXMLLoader();
   try {
      java.net.URL location = getClass().getResource("hello.fxml");
      pane = (Pane)loader.load(location);
   } catch (Exception e) {
      System.out.println("Exception" + e);
   }
}

@Override
public void start(Stage primaryStage)
{
   scene = new Scene(pane);
   //scene.getStylesheets().add("style.css");
   primaryStage.setTitle("Hello World!");
   primaryStage.setScene(scene);
   primaryStage.show();
}

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

} // end class

/****************************************************************

Good Resources:

http://fxexperience.com/

https://martinfowler.com/eaaDev/PresentationModel.html (I'm not convinced
this is a good design pattern, but need to look at it more closely)

https://stackoverflow.com/questions/32739199/javafx-software-design

https://edencoding.com/mvc-in-javafx/  (some things I like, some I don't)

https://docs.oracle.com/javafx/2/best_practices/jfxpub-best_practices.htm

*****************************************************************/

Hello FXML file

The following is in my hello.fxml file, created by SceneBuilder. Note how the onAction tags correspond to method names:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>

<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Hello">
   <top>
      <MenuBar BorderPane.alignment="CENTER">
        <menus>
          <Menu mnemonicParsing="false" text="File">
            <items>
              <MenuItem mnemonicParsing="false" onAction="#menuFileClose" text="Close" />
            </items>
          </Menu>
          <Menu mnemonicParsing="false" text="Edit">
            <items>
              <MenuItem mnemonicParsing="false" text="Delete" />
            </items>
          </Menu>
          <Menu mnemonicParsing="false" text="Help">
            <items>
              <MenuItem mnemonicParsing="false" onAction="#menuHelpAbout" text="About" />
            </items>
          </Menu>
        </menus>
      </MenuBar>
   </top>
   <center>
      <GridPane BorderPane.alignment="CENTER">
        <columnConstraints>
          <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
          <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
        </columnConstraints>
        <rowConstraints>
          <RowConstraints maxHeight="180.0" minHeight="10.0" prefHeight="78.0" vgrow="SOMETIMES" />
          <RowConstraints maxHeight="293.0" minHeight="10.0" prefHeight="293.0" vgrow="SOMETIMES" />
        </rowConstraints>
         <children>
            <Button fx:id="mybutton" mnemonicParsing="false" onAction="#mybuttonAction" text="Button" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.valignment="CENTER">
               <font>
                  <Font name="DejaVu Sans Bold" size="17.0" />
               </font>
            </Button>
            <Label fx:id="mylabel" text="Label" GridPane.halignment="CENTER" GridPane.valignment="CENTER">
               <font>
                  <Font name="DejaVu Sans Bold" size="26.0" />
               </font>
            </Label>
         </children>
      </GridPane>
   </center>
</BorderPane>

Some JavaFX Examples

FXBouncer is a small example of creating animation in JavaFX.

FXDataTable is a small example of a cleaner MVC design for a data table than is what is usually described on the internet. A more detailed discussion of it is on this page.

I have other non-FX code examples and small projects on GitHub.