Creating tray icon using JavaFX

You can't with pure JavaFX, but you can use AWT with JavaFX:

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.

code source

If this is to be believed, JavaFX will feature tray icons in a future update. Till then stick to AWT. Keep track of the development using this thread on the JDK bug system. Hope this helps.