Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Demonstrate using the System Tray (AWT) to control a JavaFX application.
import javafx.application.*;
import javafx.geometry.Pos;
import javafx.scene.*;
import javafx.scene.control.Label;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.stage.*;
import javax.imageio.ImageIO;
import java.text.*;
import java.util.*;
// Java 8 code
public class JavaFXTrayIconSample extends Application {
// one icon location is shared between the application tray icon and task bar icon.
// you could also use multiple icons to allow for clean display of tray icons on hi-dpi devices.
private static final String iconImageLoc =
// application stage is stored so that it can be shown and hidden based on system tray icon operations.
private Stage stage;
// a timer allowing the tray icon to provide a periodic notification event.
private Timer notificationTimer = new Timer();
// format used to display the current time in a tray icon notification.
private DateFormat timeFormat = SimpleDateFormat.getTimeInstance();
// sets up the javafx application.
// a tray icon is setup for the icon, but the main stage remains invisible until the user
// interacts with the tray icon.
@Override public void start(final Stage stage) {
// stores a reference to the stage.
this.stage = stage;
// instructs the javafx system not to exit implicitly when the last application window is shut.
// sets up the tray icon (using awt code run on the swing thread).
// out stage will be translucent, so give it a transparent style.
// create the layout for the javafx stage.
StackPane layout = new StackPane(createContent());
"-fx-background-color: rgba(255, 255, 255, 0.5);"
layout.setPrefSize(300, 200);
// this dummy app just hides itself when the app screen is clicked.
// a real app might have some interactive UI and a separate icon which hides the app window.
layout.setOnMouseClicked(event -> stage.hide());
// a scene with a transparent fill is necessary to implement the translucent app window.
Scene scene = new Scene(layout);
* For this dummy app, the (JavaFX scenegraph) content, just says "hello, world".
* A real app, might load an FXML or something like that.
* @return the main window application content.
private Node createContent() {
Label hello = new Label("hello, world");
hello.setStyle("-fx-font-size: 40px; -fx-text-fill: forestgreen;");
Label instructions = new Label("(click to hide)");
instructions.setStyle("-fx-font-size: 12px; -fx-text-fill: orange;");
VBox content = new VBox(10, hello, instructions);
return content;
* Sets up a system tray icon for the application.
private void addAppToTray() {
try {
// ensure awt toolkit is initialized.
// app requires system tray support, just exit if there is no support.
if (!java.awt.SystemTray.isSupported()) {
System.out.println("No system tray support, application exiting.");
// set up a system tray icon.
java.awt.SystemTray tray = java.awt.SystemTray.getSystemTray();
URL imageLoc = new URL(
java.awt.Image image =;
java.awt.TrayIcon trayIcon = new java.awt.TrayIcon(image);
// if the user double-clicks on the tray icon, show the main app stage.
trayIcon.addActionListener(event -> Platform.runLater(this::showStage));
// if the user selects the default menu item (which includes the app name),
// show the main app stage.
java.awt.MenuItem openItem = new java.awt.MenuItem("hello, world");
openItem.addActionListener(event -> Platform.runLater(this::showStage));
// the convention for tray icons seems to be to set the default icon for opening
// the application stage in a bold font.
java.awt.Font defaultFont = java.awt.Font.decode(null);
java.awt.Font boldFont = defaultFont.deriveFont(java.awt.Font.BOLD);
// to really exit the application, the user must go to the system tray icon
// and select the exit option, this will shutdown JavaFX and remove the
// tray icon (removing the tray icon will also shut down AWT).
java.awt.MenuItem exitItem = new java.awt.MenuItem("Exit");
exitItem.addActionListener(event -> {
// setup the popup menu for the application.
final java.awt.PopupMenu popup = new java.awt.PopupMenu();
// create a timer which periodically displays a notification message.
new TimerTask() {
public void run() {
javax.swing.SwingUtilities.invokeLater(() ->
"The time is now " + timeFormat.format(new Date()),
// add the application tray icon to the system tray.
} catch (java.awt.AWTException | IOException e) {
System.out.println("Unable to init system tray");
* Shows the application stage and ensures that it is brought ot the front of all stages.
private void showStage() {
if (stage != null) {;
public static void main(String[] args) throws IOException, java.awt.AWTException {
// Just launches the JavaFX application.
// Due to way the application is coded, the application will remain running
// until the user selects the Exit menu option from the tray icon.
Copy link

thierrylafaye commented Jan 22, 2021

I feel like someone should make a library for easily working with TrayIcons from JavaFX as the AWT API is not friendly to me as a JavaFX user. Guess that's another side project for me to do...

I succeeded in making this marginally easier. Have a look at my repo "FXTrayIcon", particularly at the test application that I wrote. Still uses AWT, but abstracts away some of the nastiness. FXTrayIcon

When can I come kiss you? @dustinkredmond

Star the repo and that's even better than a kiss in my opinion. :D

And so I just "kissed" you! 🤣 Thanks so much for putting some effort into this workaround. If I had the knowledge, I would have contributed to this component which seems quite needed for a decent JavaFx control set.

Copy link

AmirAli-AZ commented Jan 4, 2022

No news yet??
Thanks also to @ dustinkredmond, I hope his project helps me

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment