You are on page 1of 32

Building and Deploying Java

Client Desktop Applications


With JDK 17 and Beyond

[LRN1413 – JavaOne 2022]


Phil Race and Kevin Rushforth.
Java Desktop UI Client Team,
Java Platform Development Group, Oracle
Agenda

• Why a desktop application ?


• Quick high-level overview of the JavaFX and Swing APIs
• DEMO an email desktop client application
• Show how the UI was built
• Show how to create a deployment package for the app
• Re-examine the DEMO having explained how it was built
• Summary

3 Oracle CloudWorld Copyright © 2022, Oracle and/or its affiliates


Why a desktop application ?

• To access desktop features not easily delivered in a browser such as


• multi-window, multi-screen,
• O/S and desktop integration
• A better development experience
• maintainability,
• stability,
• control over the execution platform.
• ability to use platform libraries, native code via JNI (and in the future Project Panama)
• A better overall experience for the user
• Performance
• Responsiveness
• Easy to access application.

4 Oracle CloudWorld Copyright © 2022, Oracle and/or its affiliates


Swing[*] vs JavaFX as UI toolkits

At a distance there's a lot of similarity between the Swing/AWT/2D APIs and JavaFX APIs
• Both offer a comprehensive set of UI controls, with event handling , drag and drop, clip board, window
management ..
• Both support customization of the rendering of the UI controls
• Both provide graphics primitives and 2D geometry, transformations etc.
• Both supporting printing

[*] : Whenever we say or write just "Swing“ in this presentation we mean not just the Swing UI toolkit but
also Java 2D and AWT etc as a whole, since the old encompassing term of "JFC“ (Java Foundation
Classes) has fallen into dis-use. The phrase “JDK Client Libraries” is another way of describing all these
that are part of Java SE.

5 Oracle CloudWorld Copyright © 2022, Oracle and/or its affiliates


Swing vs JavaFX as UI toolkits (continued)

• Both make use of hardware acceleration of rendering (under the covers)


• Both are high performance
• Both support a variety of layout managers sufficient for most applications
• Both support Accessibility (for Assistive Technologies)
• Both support I18N / L10N
• Both can be developed using your preferred IDE (Idea, Eclipse, NetBeans)

6 Oracle CloudWorld Copyright © 2022, Oracle and/or its affiliates


Swing and JavaFX strengths

But each also has some unique features or greater strengths


• Swing is bundled with OpenJDK as it is part of Java SE.
• JavaFX has some 3D support
• It is easier to extend Swing components
• It is easier to style FX components
• Swing has richer text and imaging APIs
• JavaFX has built-in charting APIs
• JavaFX supports media (integrated audio and video), web, animation, effects

So which one do you choose ?

7 Oracle CloudWorld Copyright © 2022, Oracle and/or its affiliates


Swing and JavaFX can be used together !

Fortunately it is not an either/or choice – you can use both.

They work together seamlessly in the same application - even in the same
window. Swing can be nested within JavaFX – and vice versa.

And you can then interoperate between the two of them to create a first class
desktop application

8 Oracle CloudWorld Copyright © 2022, Oracle and/or its affiliates


DEMO – UI for an email client application (JMail)

• Uses both Swing and JavaFX showcasing both


• Focus is on being a first class desktop application.
• Uses only public APIs available in JDK 17 and JavaFX 17
• Is installed using a platform installer created by the JDK’s jpackage tool.
• Disclaimer : the emphasis here is on the UI - it doesn't connect to an email server and so all email data
is static.

9 Oracle CloudWorld Copyright © 2022, Oracle and/or its affiliates


Creating the Jmail Desktop Application

• What we will show you is how we developed this application


• We will help you navigate past the overwhelming amount of javadoc documentation, guides and
tutorials focused on how to use specific APIs / UI controls [*]
• We will help you find the parts you need to use to assemble the application
• We will also show how you can easily mix JavaFX and Swing
• Along the way we will use some of the powerful UI controls and capabilities of these APIs
• Then when you have the application, we will show how to deploy it.

- The take away will be you will be to apply this to build your own application for your use case.

[*] But you’ll still need these so for your reference


Creating a UI with Swing: https://docs.oracle.com/javase/tutorial/uiswing.html
Creating a UI with JavaFX: https://docs.oracle.com/javafx/index.html

10 Oracle CloudWorld Copyright © 2022, Oracle and/or its affiliates


Make a Splash !

• Applications can take time to start if they need to load files, access network resources etc
• Good UI experience gives immediate feedback that the App DID get the message to launch
• Add on command line (NO coding required)
java -splash:images/DukeMailbox.png
• Or embed the image in the jar and reference from the Manifest (META-INF/MANIFEST.MF)
SplashScreen-Image: images/DukeMailbox.png
• For best results provide splash images for different screen DPIs : Duke.png, Duke125pct.png,
Duke150pct.png, Duke200pct.png. JDK automatically selects the best match
• Splash is automatically hidden on displaying first AWT Window.
• Use the java.awt.SplashScreen API to programmatically update or hide the Splash
• Jmail applies a fadeout effect on an un-decorated replacement window.
• javax.swing.Timer fires every 20ms and calls Window.setOpacity(getOpacity()-0.05) until window
is invisible.

11 Oracle CloudWorld Copyright © 2022, Oracle and/or its affiliates


JToolBar

JFrame
JMail UI

JavaFX
TreeTableView JTable
embedded in a
JFXPanel from
the JavaFX JSplitPane
Swing interop
module JPanel with
JLabel
children
JSplitPane
JEditorPane

12 Oracle CloudWorld Copyright © 2022, Oracle and/or its affiliates


Frame It !

• JMail uses a Swing JFrame with a tool bar, folder list, messages list and message.
• The hierarchy of containers depends on how components should be grouped and what should
happen on resize
• The folder list is a JavaFX TreeTableView embedded in a JFXPanel
• The Message list is a JTable, the message view is a JPanel with multiple children
• JSplitPane is used to allow the user to reapportion the size of each grouping
• The Message JPanel children are another Panel for To/From/Subject etc
• JEditorPane is used to display the HTML content of the message text
• A variable number of JPanels display in-line attachments and the attachment list
• Choose a LayoutManager flexible enough to handle all the children of a container
as the window is resized. GridBagLayout or SpringLayout are possibilities for AWT. JavaFX has
GridPane, AnchorPane and simpler one such as HBox and VBox

13 Oracle CloudWorld Copyright © 2022, Oracle and/or its affiliates


Get Noticed! System Tray and Desktop Notifications

• Use the java.awt.SystemTray API


• Install a TrayIcon for Jmail
• Add a PopupMenu
• Use it to provide notifications when new mail arrives (etc)
import java.awt.MenuItem;
import java.awt.PopupMenu’
import java.awt.SystemTray;
import java.awt.TrayIcon;

SystemTray systemTray = SystemTray.getSystemTray();


PopupMenu popupMenu = new PopupMenu();
MenuItem item = new MenuItem(“Compose New Message”);
popupMenu.add(item);
TrayIcon trayIcon = new TrayIcon(mailImage, “Jmail”, popupMenu);
systemTray.add(trayIcon);

14 Oracle CloudWorld Copyright © 2022, Oracle and/or its affiliates


Respond to Desktop Events : Example : About Handler
import java.awt.Desktop; // Key class for desktop integration
import java.awt.desktop.AboutEvent;
import java.awt.desktop.AboutHandler;

class JMailAboutHandler implements AboutHandler {


public void handleAbout(AboutEvent aboutEvent) {
// display a modeless JDialog with info about JMail


}
///////////////////////////
if (Desktop.isDesktopSupported) {
Desktop dt = Desktop.getDesktop();
if (dt.isSupported(Desktop.ACTION.APP_ABOUT)) {
dt.setAboutHandler(new JMailAboutHandler();
}
}
///////////////////////////////

15 Oracle CloudWorld Copyright © 2022, Oracle and/or its affiliates


JavaFX/Swing InterOp : JFXPanel and SwingNode

JFXPanel – FX inside Swing

• Used to embed JavaFX content into a Swing JFrame


• JFXPanel is a Swing JComponent
• JFXPanel contains a JavaFX Scene

JFXPanel jfxPanel = new JFXPanel();


Platform.runLater(() -> {
var button = new Button("JavaFX: Click me");
button.setOnAction(e -> System.out.println("Hello from JavaFX!"));
var root = new VBox(button);
var scene = new Scene(root);
jfxPanel.setScene(scene);
});
swingPanel.add(jfxPanel, BorderLayout.CENTER);

16 Oracle CloudWorld Copyright © 2022, Oracle and/or its affiliates


JavaFX/Swing InterOp : JFXPanel and SwingNode

SwingNode : Swing inside FX

• Used to embed Swing content into a JavaFX Stage


• SwingNode is a JavaFX Node
• SwingNode contains a Swing JComponent

var jButton = new JButton("SwingNode: JButton");


jButton.addActionListener(e -> {
System.out.println("Swing: JButton in SwingNode");
});
var swingButton = new SwingNode();
swingButton.setContent(jButton);

17 Oracle CloudWorld Copyright © 2022, Oracle and/or its affiliates


Compose Yourself ! – JavaFX window and controls
JavaFX Stage
Buttons Button
Label

TextField

HTMLEditor

18 Oracle CloudWorld Copyright © 2022, Oracle and/or its affiliates


Content Handling : Text

If content type is recognized, create a handler for it and pass it


the data and add a new control in-line in the message.
Text is very straightforward.

import java.nio.files.*;
JComponent createTextPanel(String fileName) {
Path filePath = Path.of(fileName);
try {
text = Files.readString(filePath);
} catch (IOException e) {
}
return new JTextArea(text); // the important line
}

19 Oracle CloudWorld Copyright © 2022, Oracle and/or its affiliates


Content Handling : Images

• Built-in support in JDK for PNG, GIF, JPEG, TIFF, BMP images
• Straightforward to load - but first check image size in a robust app.
• Scale image down to fit – some photo images are very large.
• Wrap it in a Swing JComponent to be layed out and painted.
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
..
BufferedImage image = ImageIO.read(imageFile);
..
class ImagePanel extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, x, y, scaledWidth, scaledHeight, null);
}
}

20 Oracle CloudWorld Copyright © 2022, Oracle and/or its affiliates


Content Handling : Media

class MediaControl {
// add Play etc to wrapped MediaView
}

public static JFXPanel createMediaContent(String urlString) {


Media media = new Media(urlString);
MediaPlayer mediaPlayer = new MediaPlayer(media);
MediaView mediaView = new MediaView(mediaPlayer);
MediaControl mediaControl = new MediaControl(mediaView) ;
var scene = new Scene(mediaControl);
var jfxPanel = new JFXPanel();
jfxPanel.setScene(scene);
return jfxPanel;
}

21 Oracle CloudWorld Copyright © 2022, Oracle and/or its affiliates


Content Handling : HTML / Web using JavaFX

// urlString can be (1) local file (2) remote URL


public static JFXPanel createWebContent(String urlString) {
BorderPane root = new BorderPane();
WebView webView = new WebView();
WebEngine webEngine = webView.getEngine();
webEngine.load(urlString);
root.setCenter(webView);
// add browser navigation controls to root
...
Scene scene = new Scene(root, 400, 300);
var jfxPanel = new JFXPanel();
jfxPanel.setScene(scene);
return jfxPanel;
}

22 Oracle CloudWorld Copyright © 2022, Oracle and/or its affiliates


Content Handling : Swing Content
public class SwingContent extends JavaContent {

SwingContent(JPanel panel, String jarFileName) {


super(jarFileName); // loads the app from the jar
if (theUI instanceof JComponent swingUI) {
panel.setLayout(new BorderLayout());
panel.add(BorderLayout.CENTER, swingUI);
}
}
}

23 Oracle CloudWorld Copyright © 2022, Oracle and/or its affiliates


Content Handling : JavaFX Content
public FXContent(JFXPanel jfxPanel, String jarFileName) {
super(jarFileName); // loads app

if (theUI instanceof Parent fxUI) {


var root = new BorderPane();
scene = new Scene(root);
root.setCenter(fxUI);
jfxPanel.setScene(scene);
}
}

24 Oracle CloudWorld Copyright © 2022, Oracle and/or its affiliates


Content Handling : External applications
Not all content can be handled by the JavaFX and Swing built-in support, eg
• PDF docs
• Microsoft Office docs, OpenOffice docs, macOS Keynote presentations
• Sometimes you want content in an external application even if JDK can handle it.

Launch a known application from a path using java.lang.ProcessBuilder

String javaHome = System.getProperty("java.home", "");


String javaCmd = Path.of(javaHome, "bin", "java").toString();
new ProcessBuilder(javaCmd, “-jar”, “Pie.jar”).start();

Use the java.awt.Desktop handler to find the desktop content handler

Desktop.getDesktop().browse(new URI(https://openjdk.org)); // open platform web browser


Desktop.getDesktop().open(new File(“duke.pdf”); // open platform PDF viewer

25 Oracle CloudWorld Copyright © 2022, Oracle and/or its affiliates


What isn’t in the demo ?

Not enough time to create or show everything, but for your app also consider :

• Using a custom Swing L&F or CSS styling of JavaFX controls


• Drag and Drop support
• Custom cursors
• Animation
• Graphic effects
• Etc …

26 Oracle CloudWorld Copyright © 2022, Oracle and/or its affiliates


Deploying JMail using the jpackage tool

Step 1 - Build your JDK runtime containing both Swing and JavaFX

First create the JDK to include in the application based on JDK 19 and OpenJFX 19 using the JDK’s jlink
command line tool.

The commands assume


(1) JDK 19 is on the current PATH
(2) JDK 19 jmods are in $JAVA_HOME/jmods
(3) JavaFX 19 jmods are in javafx-jmods-19

jlink --output jdk-19+javafx-19 \


--module-path $JAVA_HOME/jmods:javafx-jmods-19 \
--add-modules ALL-MODULE-PATH

27 Oracle CloudWorld Copyright © 2022, Oracle and/or its affiliates


Deploying JMail using the jpackage tool (continued)

Step 2 – Run the JDK’s jpackage command line tool

Now issue the jpackage command - a basic example looks like

jpackage --main-jar jmail.jar --runtime-image jdk-19+javafx-19


--name JMail --input jmail.dir --dest jpkg.outdir

• This will create JMail.exe on Windows, JMail.dmg on MacOS


• Override as needed using appropriate options to create a macOS .pkg, Windows .msi .. Etc

28 Oracle CloudWorld Copyright © 2022, Oracle and/or its affiliates


Deploying JMail using the jpackage tool (continued)

Since we are emphasizing being a 1st class desktop app, you should look at jpackage platform options

Windows : Add app to the Windows Menu and have installer create a desktop shortcut.
Provide an application icon in Windows required format.
jpackage .. --win-menu --win-shortcut –icon jmail.ico ..

macOS : Specify name to be used on the menu bar


Provide application icon for use on the Dock in macOS format.
jpackage .. –mac-package-name "JMail App" –icon jmail.iconset/jmail.icons ...

• There are numerous other platform-specific options – refer to jpackage docs.


• Install the .exe or .dmg in the usual way as any application.
• Docs on using jpackage are here: https://docs.oracle.com/en/java/javase/19/jpackage/

29 Oracle CloudWorld Copyright © 2022, Oracle and/or its affiliates


Re-examine the JMail app (DEMO)

Look at the JMail app again now we know how it was implemented

DEMO (time permitting) of running jpackage and installing the app

30 Oracle CloudWorld Copyright © 2022, Oracle and/or its affiliates


Summary

• We have covered how to build a modern desktop application using both the Swing and JavaFX APIs
• We have looked at the desktop integration features these provide
• We have seen how easy it is to handle multiple content types
• We have learned how to use jpackage to create platform installers
• We have provided pointers to documentation

Shortly after Oracle Cloudworld / JavaOne 2022 we expect to post some of the content we have covered
here for you to review code etc at your leisure : https://cr.openjdk.java.net/~prr/javaone/2022/

You now have the information you need to start to build your own Java desktop UI application.

MORE ABOUT JAVAFX: “JavaFX 19 and Beyond” [LRN2615], THIS room, 2.30pm Thursday.

31 Oracle CloudWorld Copyright © 2022, Oracle and/or its affiliates

You might also like