3

On Mac OS, applications that run in the background sometimes have their icon attached to a gui or menu in the right corner of the screen. I believe it is similar to what Windows has on the bottom-right corner. However I want this for my JavaFX application as well. And I don't know how to google for that. All I found was JavaFX' MenuBar, what unfortunately is not what I'm looking for.

Example of what I want for my application

primarykey123
  • 137
  • 1
  • 9
  • To clarify, using [`MenuBar`](https://openjfx.io/javadoc/11/javafx.controls/javafx/scene/control/MenuBar.html) with [`useSystemMenuBar`](https://openjfx.io/javadoc/11/javafx.controls/javafx/scene/control/MenuBar.html#useSystemMenuBarProperty) set to `true` is _not_ what you want, correct? Are you looking for something like [`SystemTray`](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/java/awt/SystemTray.html)? If so, take a look at [JavaFX app in System Tray](https://stackoverflow.com/questions/12571329/javafx-app-in-system-tray). – Slaw Nov 02 '18 at 23:26
  • Thank you! SystemTray did the trick. – primarykey123 Nov 04 '18 at 20:24

3 Answers3

0

You need to set a system property in order to move it out from your JFrame:

System.setProperty("apple.laf.useScreenMenuBar", "true");

This will show your JMenuBar in the MacOS Toolbar.

Or you could check if you are running MacOS and then set the property:

  if (System.getProperty("os.name").contains("Mac")) {
  System.setProperty("apple.laf.useScreenMenuBar", "true");

}
FileInputStream
  • 126
  • 2
  • 11
  • This is not what the OP is asking for. He asks for the system tray and NOT for the toolbar and also he is talking about JavaFX and not Swing. – mipa Jul 19 '19 at 15:52
0
public class SystemTray {
    private static final Logger logger = LogManager.getLogger(Main.class);
    public static java.awt.SystemTray tray = java.awt.SystemTray.getSystemTray();              // set up a system tray icon.
    public static TrayIcon trayIcon;
    public static Image trayIconImage;
    public static MenuItem startRecording;
    public static MenuItem stopRecording;
    public static MenuItem playRecording;
    public static MenuItem pauseRecording;
    public static MenuItem startOver;
    public static MenuItem exitItem;
    final static PopupMenu popup=new PopupMenu();
    public static boolean windows = Main.checkOS();

    public SystemTray() {
    }

    public static void addAppToTray() {
        try {
            // ensure awt toolkit is initialized.
            Toolkit.getDefaultToolkit();
            URL IconPath;
            // 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.");
                return;
                //Platform.exit();
            }

            if (windows) {
            File file = new File("./resources/main/cogwheel-win.png");
           // IconPath =this.getClass().getResource("cogwheel-windows.png");
            IconPath =file.toURI().toURL();

            }
            else {
            File file = new File("./resources/main/cogwheel-mac.png");
           // IconPath =this.getClass().getResource("cogwheel-mac.png");
            IconPath =file.toURI().toURL();
            }

            logger.info(IconPath.getFile().toString());
            trayIconImage = ImageIO.read(IconPath);
            trayIcon = new TrayIcon(trayIconImage);
            startRecording = new MenuItem("Start Recording (Shift+Space)");
            stopRecording = new MenuItem("Stop Recording (Shift+Space)");
            playRecording = new MenuItem("Play Recording (Shift+P)");
            pauseRecording = new MenuItem("Pause Recording (Shift+P)");
            startOver = new MenuItem("Start Over (Shift+R)");
            //openItem.addActionListener(event -> Platform.runLater(this::showStage));

            // and select the exit option, this will shutdown JavaFX and remove the
            // tray icon (removing the tray icon will also shut down AWT).

            exitItem = new MenuItem("Quit CAD");
            exitItem.addActionListener(event -> {
                Platform.exit();
                tray.remove(trayIcon);
            });

            // setup the popup menu for the application.
            popup.add(startRecording);
            popup.add(stopRecording);
            popup.addSeparator();
            popup.add(playRecording);
            popup.add(pauseRecording);
            popup.addSeparator();
            popup.add(startOver);
            popup.addSeparator();
            popup.add(exitItem);
            trayIcon.setPopupMenu(popup);
            // add the application tray icon to the system tray.
            tray.add(trayIcon);

           // startRecording.addActionListener(event -> Platform.runLater(Creator::startRecording));

        } catch (AWTException | IOException e) {
            System.out.println("Unable to init system tray");
           logger.info(e.getMessage());
        }
    }
}
Timo Türschmann
  • 4,388
  • 1
  • 22
  • 30
0

I write apps like this a lot, and this is what I discovered as being the easiest and most effective way to use Java/FX to create an app on MacOS that only exists as an icon in the system tray.

I utilize the FXTrayIcon library to accomplish this as that library does the conversions between JavaFX and AWT quite nicely.

First I just add this to my POM file:

<dependency>
    <groupId>com.dustinredmond.fxtrayicon</groupId>
    <artifactId>FXTrayIcon</artifactId>
    <version>3.3.0</version>
</dependency>

Then I use a Launcher class which takes advantage of what AWT can do that JavaFX cannot which is get rid of the Dock icon (not to mention still no native FX support for the system tray).

import java.awt.*;

public class Launcher {
    public static void main(String[] args) {
        System.setProperty("apple.awt.UIElement", "true");
        Toolkit.getDefaultToolkit();
        Main.main(args);
    }
}

Then here is a simple Main class that is fully functional

import com.dustinredmond.fxtrayicon.FXTrayIcon;
import javafx.application.Application;
import javafx.stage.Stage;

import java.net.URL;

public class Main extends Application {

    private URL icon = Main.class.getResource("icon.png");

    @Override public void start(Stage primaryStage) throws Exception {
        new FXTrayIcon.Builder(primaryStage, icon, 22, 22)
                .menuItem("Say Hello", e->helloIcon())
                .separator()
                .addExitMenuItem("Exit", e-> System.exit(0))
                .show()
                .build();
    }

    private void helloIcon() {
        System.out.println("Hello Icon");
    }

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

This is what it looks like, and no Dock icon at all nor does the app show up in the CMD+TAB app switching.

Screen Shot

Michael Sims
  • 2,360
  • 1
  • 16
  • 29