JavaFX

Content:

  1. What it is
  2. Status
  3. History
  4. Philosophy
  5. Simple examples
  6. Browser and media
  7. Combining Swing and JavaFX
  8. Applets
  9. Future

What it is:

JavaFX is a new GUI framework for Java. It is supplementing/replacing Swing.

Latest GUI framework for Java:

Java version Years GUI framework
1.0-1.1 1996-1998 AWT
1.2-1.7 1998-2014 Swing
1.8- 2014- JavaFX

Status:

JavaFX is integrated into Oracle JRE and JDK since Java 8.

Note that it is not part of the Java SE specification and as a result then other Java implementations like IBM Java does not have JavaFX. The practical impact is small as Oracle is dominating the Java on desktop marker.

Java 7 got JavaFX bundled since update 6.

For Java 6 and early versions of Jav a7 it is possible to download JavaFX as a separate kit:

http://www.oracle.com/technetwork/java/javafx2-archive-download-1939373.html

History:

JavaFX has a long history.

JavaFX 1.0 was released back in 2008.

But JavaFX 1.x is very different than JavaFX 2.x and 8.x.

JavaFX 1.x consisted of a library and a new language called JavaFX Script.

JavaFX Script was a very interesting language with a syntax that combined normal imperative programming logic and declarative definition of GUI layout.

JavaFX 2.0 was release in 2011 and changed a lot:

JavaFX 2.2.7 is the version bundled with Java 7 update 6.

JavaFX 8.0 is the version part of (Oracle) Java 8.

And if someone is interested then JavaFX Script lives on in two open source projects:

According to rumours then first Sun and later Oracle has spent many millions of dollars developing JavaFX.

Philosophy:

The idea behind JavaFX 2.x is copied from Adobe and Microsoft.

Adobe Flex introduced the concept of separation in markup and code for GUI applications in 2004 (MXML and AcrionScript).

Microsoft started using the concept in 2006 with WPF (XAML and C#).

Oracle replaced JavaFX 1.x with the mixed imperative and declarative code in 2008 with FXML and Java.

JavaFX also got some features from traditional web technology:

JavaFX is a very large framework. For Java 8 then jfxrt.jar with JavaFX is 18 MB and rt.jar with most of the rest is 63 MB.

Simple examples:

I will illustrate the possibilities in JavaFX with a little GUI application. The functionality is unrealistic simple and the visual design is bad, but I think it is OK to demo the capabilities of JavaFX.

First a "business logic" class to be used by the GUI.

Calculator.java:

package demo;

public class Calculator {
    private double number;
    public void setNumber(double number) {
        this.number = number;
    }
    public double getSqrt() {
        return Math.sqrt(number);
    }
    public double getLog() {
        return Math.log(number);
    }
    public double getExp() {
        return Math.exp(number);
    }
}

Let us start by doing the GUI using traditional Swing.

SwingGUI.java:

package demo;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class SwingGUI extends JFrame {
    private Calculator data = new Calculator();
    private JTextField number;
    private JLabel sqrt;
    private JLabel log;
    private JLabel exp;
    public SwingGUI() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setTitle("Swing GUI");
        getContentPane().setLayout(new GridLayout(5, 2));
        getContentPane().setBackground(Color.YELLOW);
        getContentPane().add(new JLabel("Number"));
        number = new JTextField();
        getContentPane().add(number);
        getContentPane().add(new JLabel("Square root"));
        sqrt = new JLabel();
        sqrt.setForeground(Color.BLUE);
        getContentPane().add(sqrt);
        getContentPane().add(new JLabel("Logarithm"));
        log = new JLabel();
        log.setForeground(Color.BLUE);
        getContentPane().add(log);
        getContentPane().add(new JLabel("Exponential"));
        exp = new JLabel();
        exp.setForeground(Color.BLUE);
        getContentPane().add(exp);
        JButton calc = new JButton("Calculate");
        calc.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                double x = Double.parseDouble(number.getText());
                data.setNumber(x);
                sqrt.setText(Double.toString(data.getSqrt()));
                log.setText(Double.toString(data.getLog()));
                exp.setText(Double.toString(data.getExp()));
            }
        });
        calc.setBackground(Color.RED);
        getContentPane().add(calc);
        pack();
    }
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JFrame f = new SwingGUI();
                f.setVisible(true);
            }
        });
    }
}

It works fine but:

Now we create the same code using JavaFX without FXML.

OldStyleJavaFX.java:

package demo;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;

public class OldStyleJavaFXGUI extends Application {
    private Calculator data = new Calculator();
    private TextField number;
    private Label sqrt;
    private Label log;
    private Label exp;
    @Override
    public void start(Stage stg) throws Exception {
        stg.setTitle("Old style JavaFX GUI");
        GridPane pn = new GridPane();
        pn.setStyle("-fx-background-color: yellow;");
        number = new TextField();
        pn.add(new Label("Number"), 0, 0);
        pn.add(number, 1, 0);
        pn.add(new Label("Square root"), 0, 1);
        sqrt = new Label();
        sqrt.setStyle("-fx-text-fill: blue;");
        pn.add(sqrt, 1, 1);
        pn.add(new Label("Logarithm"), 0, 2);
        log = new Label();
        log.setStyle("-fx-text-fill: blue;\"");
        pn.add(log, 1, 2);
        pn.add(new Label("Exponential"), 0, 3);
        exp = new Label("");
        exp.setStyle("-fx-text-fill: blue;\"");
        pn.add(exp, 1, 3);
        Button calc = new Button("Calculate");
        calc.setStyle("-fx-background-color: red;");
        calc.setOnAction((e) -> {
            double x = Double.parseDouble(number.getText());
            data.setNumber(x);
            sqrt.setText(Double.toString(data.getSqrt()));
            log.setText(Double.toString(data.getLog()));
            exp.setText(Double.toString(data.getExp()));
        });
        pn.add(calc, 0, 4);
        Scene scn = new Scene(pn);
        stg.setScene(scn);
        stg.show();
    }
    public static void main(String[] args) {
        Application.launch(OldStyleJavaFXGUI.class, args);
    }
}

The code is sligthly cleaner but no big difference.

Look & feel is much more modern.

Now we move layout and styling to FXML and CSS.

TrueJavaFXGUI.java:

package demo;

import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.stage.Stage;

public class TrueJavaFXGUI extends Application {
    private Calculator data = new Calculator();
    @FXML
    private TextField number;
    @FXML
    private Label sqrt;
    @FXML
    private Label log;
    @FXML
    private Label exp;
    @Override
    public void start(Stage stg) throws Exception {
        stg.setTitle("True JavaFX GUI");
        Scene scn = new Scene((Parent) FXMLLoader.load(getClass().getResource("JavaFXGUI.fxml")));
        scn.getStylesheets().add(getClass().getResource("JavaFXGUI.css").toString());
        stg.setScene(scn);
        stg.show();
    }
    public void calcClick() {
        double x = Double.parseDouble(number.getText());
        data.setNumber(x);
        sqrt.setText(Double.toString(data.getSqrt()));
        log.setText(Double.toString(data.getLog()));
        exp.setText(Double.toString(data.getExp()));
    }
    public static void main(String[] args) {
        Application.launch(TrueJavaFXGUI.class, args);
    }
}

JavaFXGUI.fxml:

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

<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<GridPane xmlns:fx="http://javafx.com/fxml" fx:controller="demo.TrueJavaFXGUI">
    <Label GridPane.columnIndex="0" GridPane.rowIndex="0" text="Number"/>
    <TextField GridPane.columnIndex="1" GridPane.rowIndex="0" fx:id="number"/>
    <Label GridPane.columnIndex="0" GridPane.rowIndex="1" text="Square root"/>
    <Label GridPane.columnIndex="1" GridPane.rowIndex="1" fx:id="sqrt"/>
    <Label GridPane.columnIndex="0" GridPane.rowIndex="2" text="Logarithm"/>
    <Label GridPane.columnIndex="1" GridPane.rowIndex="2" fx:id="log"/>
    <Label GridPane.columnIndex="0" GridPane.rowIndex="3" text="Exponential"/>
    <Label GridPane.columnIndex="1" GridPane.rowIndex="3" fx:id="exp"/>
    <Button GridPane.columnIndex="0" GridPane.rowIndex="4" text="Calculate" fx:id="calc" onAction="#calcClick" />
</GridPane>

JavaFXGUI.css:

.root {
    -fx-background-color: yellow;
}

.button {
    -fx-background-color: red;
}

#sqrt, #log, #exp {
    -fx-text-fill: blue;
}

Now we can really see the progress. Code, layout and styling are clearly separated.

The click event code can be moved from Java to JavaScript.

First inline in FXML.

TrueJavaFXGUIwithJS.java:

package demo;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class TrueJavaFXGUIwithJS extends Application {
    private Calculator data = new Calculator();
    @Override
    public void start(Stage stg) throws Exception {
        stg.setTitle("True JavaFX GUI with JavaScript");
        Scene scn = new Scene((Parent) FXMLLoader.load(getClass().getResource("JavaFXGUIwithJS.fxml")));
        scn.getStylesheets().add(getClass().getResource("JavaFXGUI.css").toString());
        stg.setScene(scn);
        stg.show();
    }
    public Calculator getData() {
        return data;
    }
    public static void main(String[] args) {
        Application.launch(TrueJavaFXGUIwithJS.class, args);
    }
}

JavaFXGUIwithJS.fxml:

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

<?language javascript?>

<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<GridPane xmlns:fx="http://javafx.com/fxml" fx:controller="demo.TrueJavaFXGUIwithJS">
    <fx:script>
        function calcClick() {
            x = parseFloat(number.text);
            controller.data.number = x;
            sqrt.text = controller.data.sqrt.toString();
            log.text = controller.data.log.toString();
            exp.text = controller.data.exp.toString();
        }
    </fx:script>
    <Label GridPane.columnIndex="0" GridPane.rowIndex="0" text="Number"/>
    <TextField GridPane.columnIndex="1" GridPane.rowIndex="0" fx:id="number"/>
    <Label GridPane.columnIndex="0" GridPane.rowIndex="1" text="Square root"/>
    <Label GridPane.columnIndex="1" GridPane.rowIndex="1" fx:id="sqrt"/>
    <Label GridPane.columnIndex="0" GridPane.rowIndex="2" text="Logarithm"/>
    <Label GridPane.columnIndex="1" GridPane.rowIndex="2" fx:id="log"/>
    <Label GridPane.columnIndex="0" GridPane.rowIndex="3" text="Exponential"/>
    <Label GridPane.columnIndex="1" GridPane.rowIndex="3" fx:id="exp"/>
    <Button GridPane.columnIndex="0" GridPane.rowIndex="4" text="Calculate" fx:id="calc" onAction="calcClick()" />
</GridPane>

And with extern JS file.

TrueJavaFXGUIwithExtJS.java:

package demo;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class TrueJavaFXGUIwithExtJS extends Application {
    private Calculator data = new Calculator();
    @Override
    public void start(Stage stg) throws Exception {
        stg.setTitle("True JavaFX GUI with external JavaScript");
        Scene scn = new Scene((Parent) FXMLLoader.load(getClass().getResource("JavaFXGUIwithExtJS.fxml")));
        scn.getStylesheets().add(getClass().getResource("JavaFXGUI.css").toString());
        stg.setScene(scn);
        stg.show();
    }
    public Calculator getData() {
        return data;
    }
    public static void main(String[] args) {
        Application.launch(TrueJavaFXGUIwithExtJS.class, args);
    }
}

JavaFXGUIwithExtJS.fxml:

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

<?language javascript?>

<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<GridPane xmlns:fx="http://javafx.com/fxml" fx:controller="demo.TrueJavaFXGUIwithJS">
    <fx:script source="JavaFXGUI.js"/>
    <Label GridPane.columnIndex="0" GridPane.rowIndex="0" text="Number"/>
    <TextField GridPane.columnIndex="1" GridPane.rowIndex="0" fx:id="number"/>
    <Label GridPane.columnIndex="0" GridPane.rowIndex="1" text="Square root"/>
    <Label GridPane.columnIndex="1" GridPane.rowIndex="1" fx:id="sqrt"/>
    <Label GridPane.columnIndex="0" GridPane.rowIndex="2" text="Logarithm"/>
    <Label GridPane.columnIndex="1" GridPane.rowIndex="2" fx:id="log"/>
    <Label GridPane.columnIndex="0" GridPane.rowIndex="3" text="Exponential"/>
    <Label GridPane.columnIndex="1" GridPane.rowIndex="3" fx:id="exp"/>
    <Button GridPane.columnIndex="0" GridPane.rowIndex="4" text="Calculate" fx:id="calc" onAction="calcClick()" />
</GridPane>

JavaFXGUI.js:

function calcClick() {
    x = parseFloat(number.text);
    controller.data.number = x;
    sqrt.text = controller.data.sqrt.toString();
    log.text = controller.data.log.toString();
    exp.text = controller.data.exp.toString();
}

It is actually also possible to move the click event code to a separate Java class.

TrueJavaFXGUISplitMain.java:

package demo;

import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.stage.Stage;

public class TrueJavaFXGUISplitMain extends Application {
    @Override
    public void start(Stage stg) throws Exception {
        stg.setTitle("True JavaFX GUI");
        FXMLLoader loader = new FXMLLoader(getClass().getResource("JavaFXGUISplit.fxml"));
        Scene scn = new Scene((Parent)loader.load());
        scn.getStylesheets().add(getClass().getResource("JavaFXGUI.css").toString());
        stg.setScene(scn);
        stg.show();
        TrueJavaFXGUISplitForm f = (TrueJavaFXGUISplitForm)loader.getController();
        f.setNumber(1.0);
        f.calcClick();
    }
    public static void main(String[] args) {
        Application.launch(TrueJavaFXGUISplitMain.class, args);
    }
}

TrueJavaFXGUISplitForm.java:

package demo;

import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.stage.Stage;

public class TrueJavaFXGUISplitForm {
    private Calculator data = new Calculator();
    @FXML
    private TextField number;
    @FXML
    private Label sqrt;
    @FXML
    private Label log;
    @FXML
    private Label exp;
    public void calcClick() {
        double x = Double.parseDouble(number.getText());
        data.setNumber(x);
        sqrt.setText(Double.toString(data.getSqrt()));
        log.setText(Double.toString(data.getLog()));
        exp.setText(Double.toString(data.getExp()));
    }
    public void setNumber(double x) {
        number.setText(Double.toString(x));
    }
}

JavaFXGUISplit.fxml:

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

<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<GridPane xmlns:fx="http://javafx.com/fxml" fx:controller="demo.TrueJavaFXGUISplitForm">
    <Label GridPane.columnIndex="0" GridPane.rowIndex="0" text="Number"/>
    <TextField GridPane.columnIndex="1" GridPane.rowIndex="0" fx:id="number"/>
    <Label GridPane.columnIndex="0" GridPane.rowIndex="1" text="Square root"/>
    <Label GridPane.columnIndex="1" GridPane.rowIndex="1" fx:id="sqrt"/>
    <Label GridPane.columnIndex="0" GridPane.rowIndex="2" text="Logarithm"/>
    <Label GridPane.columnIndex="1" GridPane.rowIndex="2" fx:id="log"/>
    <Label GridPane.columnIndex="0" GridPane.rowIndex="3" text="Exponential"/>
    <Label GridPane.columnIndex="1" GridPane.rowIndex="3" fx:id="exp"/>
    <Button GridPane.columnIndex="0" GridPane.rowIndex="4" text="Calculate" fx:id="calc" onAction="#calcClick" />
</GridPane>

Note the little trick to enable the main class to access the form class.

Also note that even if you use the same class for application main and form controller, then you will still get two intances of the class. So using a single class and using non-static fields to provide access between application main and form controller will not work!

Browser and media:

JavaFX has a control for an embedded browser. The browser is build on WebKit (like Chrome, iPhone and Android browsers).

JavaFXBrowser.java:

package demo;

import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.web.WebView;
import javafx.stage.Stage;

public class JavaFXBrowser extends Application {
    @FXML
    private WebView brws;
    @Override
    public void start(Stage stg) throws Exception {
        stg.setTitle("JavaFX with embedded browser");
        Scene scn = new Scene((Parent) FXMLLoader.load(getClass().getResource("JavaFXBrowser.fxml")));
        stg.setScene(scn);
        stg.show();
    }
    public void eksperten() {
        brws.getEngine().load("http://www.eksperten.dk/");
    }
    public void google() {
        brws.getEngine().load("http://www.google.com/");
    }
    public static void main(String[] args) {
        Application.launch(JavaFXBrowser.class, args);
    }
}

JavaFXBrowser.fxml:

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

<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.web.*?>

<BorderPane xmlns:fx="http://javafx.com/fxml" fx:controller="demo.JavaFXBrowser">
    <center>
        <WebView fx:id="brws"/>
    </center>
    <bottom>
        <GridPane >
            <Button GridPane.columnIndex="0" GridPane.rowIndex="0" text="Go to eksperten.dk" onAction="#eksperten" />
            <Button GridPane.columnIndex="1" GridPane.rowIndex="0" text="Go to Google" onAction="#google" />
        </GridPane>
    </bottom>
</BorderPane>

JavaFX also has a control for embedded media player.

JavaFXPlayer.java:

package demo;

import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
import javafx.stage.Stage;

public class JavaFXPlayer extends Application {
    @FXML
    private MediaView media;
    @Override
    public void start(Stage stg) throws Exception {
        stg.setTitle("JavaFX with embedded player");
        Scene scn = new Scene((Parent) FXMLLoader.load(getClass().getResource("JavaFXPlayer.fxml")), 800, 600);
        stg.setScene(scn);
        stg.show();
    }
    public void video() {
        media.setMediaPlayer(new MediaPlayer(new Media("file:///c:/work/test.flv")));
        media.setFitWidth(2*360);
        media.setFitHeight(2*288);
        media.getMediaPlayer().setAutoPlay(true);
    }
    public void audio() {
        media.setMediaPlayer(new MediaPlayer(new Media("file:///c:/work/test.mp3")));
        media.getMediaPlayer().setAutoPlay(true);
    }
    public static void main(String[] args) {
        Application.launch(JavaFXPlayer.class, args);
    }
}

JavaFXPlayer.fxml:

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

<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.media.*?>

<BorderPane xmlns:fx="http://javafx.com/fxml" fx:controller="demo.JavaFXPlayer">
    <center>
        <MediaView fx:id="media"/>
    </center>
    <bottom>
        <GridPane >
            <Button GridPane.columnIndex="0" GridPane.rowIndex="0" text="Video sample" onAction="#video" />
            <Button GridPane.columnIndex="1" GridPane.rowIndex="0" text="Audio sample" onAction="#audio" />
        </GridPane>
    </bottom>
</BorderPane>

Note the the selection of supported video and audio formats are rather limited.

Combining Swing and JavaFX:

It is possible to use JavaFX components in a Swing application.

It is not possible to use Swing components in a JavaFX application in JavaFX 2.x and 8.x (it was possible in JavaFX 1.x and maybe Oracle will reintroduce the capability later).

MixedGUI.java:

package demo;

import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class MixedGUI extends JFrame {
    public MixedGUI() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setTitle("Mixed GUI");
        getContentPane().setLayout(new GridLayout(2, 1));
        JButton swinghi = new JButton("Swing hi");
        JLabel swingtxt = new JLabel("                                                 ");
        swinghi.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                swingtxt.setText("Hi from Swing");
            }
        });
        JPanel p = new JPanel();
        p.setLayout(new BorderLayout());
        p.add(swinghi, BorderLayout.WEST);
        p.add(swingtxt, BorderLayout.EAST);
        getContentPane().add(p);
        JFXPanel fxp = new JFXPanel();
        getContentPane().add(fxp);
        pack();
        Platform.runLater(() -> {
            Button javafxhi = new Button("JavaFX hi");
            Label javafxtxt = new Label("                                                 ");
            javafxhi.setOnAction((e) -> {
                javafxtxt.setText("Hi from JavaFX");
            });
            BorderPane bp = new BorderPane();
            bp.setLeft(javafxhi);
            bp.setRight(javafxtxt);
            Scene scn = new Scene(bp);
            fxp.setScene(scn);
        });
    }
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JFrame f = new MixedGUI();
                f.setVisible(true);
            }
        });
    }
}

I will recommend against mixing Swing and JavaFX. Different look & feel, 2 event threads etc. will create lots of problems.

Applets:

JavaFX can also be used for applets.

Future:

As seen in previous sections then JavaFX comes with a lot of new and exciting technology compared to Swing.

But I don't think JavaFX will become a huge success.

Java applets has long been considered obsolete compared to Flash and Silverlight. And now all of applets, Flash and Silverlight is being dropped for HTML 5. For many reasons including support in mobile browsers.

Java desktop applications has never been a big success.

For smartphone applications then Google has chose to give Android its own GUI framework.

I don't think the progress from Swing to JavaFX will be sufficient to make JavaFX a success for desktop applications.

But if you:

then JavaFX is perfect for you.

UPDATE: I am seeing good traction for JavaFX replacing Swing for Java desktop application, but I am not seeing any significant increase in Java for desktop applications.

UPDATE: it has been announced that JavaFX will become a separate download again from Java 11 (18.9 LTS).

Article history:

Version Date Description
1.0 July 28th 2013 Initial version (in Danish) published on Eksperten.dk
2.0 September 2nd 2016 Translation to English and complete reformatting and publishing here
2.1 October 8th 2016 Add content overview
2.2 November 26th 2016 Add split example
2.2 August 9th 2018 Add note about Java 11 change in distribution

Other articles:

See list of all articles here

Comments:

Please send comments to Arne Vajhøj