Status menu with JavaFX on MacOS

Viewed 249

Is there way to create status menu with JavaFX? Documentation of JavaFX seems doesn't have anything similar. enter image description here

Left side menu is pretty simple:

MenuBar menuBar = new MenuBar();
menuBar.useSystemMenuBarProperty().set(true);

Menu menu = new Menu("java");
MenuItem item = new MenuItem("Test");
menu.getItems().add(item);
menuBar.getMenus().add(menu);

BorderPane borderPane = new BorderPane();
borderPane.setTop(menuBar);
primaryStage.setScene(new Scene(borderPane));
primaryStage.show();
1 Answers

So, there is way to show menu with java.awt.SystemTray:

public static void showMenu(Image trayImage, String... items) {

    if (!java.awt.SystemTray.isSupported())
        throw new UnsupportedOperationException("No system tray support, application exiting.");

    java.awt.Toolkit.getDefaultToolkit();

    java.awt.SystemTray tray = java.awt.SystemTray.getSystemTray();
    java.awt.TrayIcon trayIcon = new java.awt.TrayIcon(trayImage);
    java.awt.PopupMenu rootMenu = new java.awt.PopupMenu();

    for (String item : items) rootMenu.add(new MenuItem(item));

    trayIcon.setPopupMenu(rootMenu);

    try {
        tray.add(trayIcon);
    } catch (Throwable e) {
        throw new RuntimeException("Unable to init system tray");
    }
}

SystemTray supports only image as root item, but there is way to convert text into image:

static BufferedImage textToImage(String text) {
    return textToImage(text, java.awt.Font.decode(null), 13);
}

static BufferedImage textToImage(String Text, Font font, float size) {
    font = font.deriveFont(size);

    FontRenderContext frc = new FontRenderContext(null, true, true);

    LineMetrics lm = font.getLineMetrics(Text, frc);
    Rectangle2D r2d = font.getStringBounds(Text, frc);
    BufferedImage img = new BufferedImage((int) Math.ceil(r2d.getWidth()), (int) Math.ceil(r2d.getHeight()), BufferedImage.TYPE_INT_ARGB);
    Graphics2D g2d = img.createGraphics();
    g2d.setRenderingHints(RenderingProperties);
    g2d.setBackground(new Color(0, 0, 0, 0));
    g2d.setColor(Color.BLACK);

    g2d.clearRect(0, 0, img.getWidth(), img.getHeight());
    g2d.setFont(font);
    g2d.drawString(Text, 0, lm.getAscent());
    g2d.dispose();

    return img;
}

And final usage example:

public static void main(String[] args) {
    System.setProperty("apple.awt.UIElement", "true");
    showMenu(textToImage("Hello"), "Item - 1", "Item - 2");
}

System property apple.awt.UIElement=true is useful when you need to get rid of default java menu and cmd-tab icon, so your app behaves like it's background.

Related