javaswingsystem-trayjpopupmenu

How to set location of JPopupMenu relative to system tray icon and when or how to close?


I am using JPopupMenu for SystemTray pop up menu but the first problem is how to identify the safest location to place the pop up menu?

The second one How or when to stop display the popup menu? I saw this post but I can't understand the code.

Here is my sample code:


import java.awt.AWTException;
import java.awt.SystemTray;
import java.awt.TrayIcon;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;

public class SampleTrayIcon implements MouseListener, MouseMotionListener {
    /**
     * System Tray
     */
    private final SystemTray tray = SystemTray.getSystemTray();

    /**
     * Note Tray icon
     */
    private final TrayIcon trayIcon;

    /**
     * Note Tray icon popup menu
     */
    private final JPopupMenu popUpMenu = new JPopupMenu();

    /**
     * constructor
     */
    public SampleTrayIcon() {
        // check system tray is supported
        if (!SystemTray.isSupported()) {
            System.err.println("System tray is not supported");
            System.exit(1);
        }

        // Create a TrayIcon image
        BufferedImage image = null;

        // try to read image from resources
        try {
            image = ImageIO.read(new URL("https://i.sstatic.net/lM3aS.png"));
        } catch (Exception e) {
            System.err.println("Failed to read image from resources");
            System.exit(1);
        }

        // Create a TrayIcon
        trayIcon = new TrayIcon(image, "QuickNote");

        // set icon auto resize
        trayIcon.setImageAutoSize(true);

        // Create Menu items
        var viewOnHover = new JCheckBoxMenuItem("onHover");
        var aboutMenuItem = new JMenuItem("About");
        var exitMenuItem = new JMenuItem("Exit");

        // add Menuitems to PopUpMenu
        popUpMenu.add(viewOnHover);
        popUpMenu.addSeparator();
        popUpMenu.add(aboutMenuItem);
        popUpMenu.add(exitMenuItem);

        // add mouse listener to tray icon
        trayIcon.addMouseListener(this);
        trayIcon.addMouseMotionListener(this);

        // add tray to system
        try {
            tray.add(trayIcon);
        } catch (AWTException e) {
            System.err.println("TrayIcon could not be added to system tray");
            System.exit(1);
        }
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        // TODO Auto-generated method stub
    }

    @Override
    public void mouseMoved(MouseEvent e) {
        // TODO Auto-generated method stub
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        if(SwingUtilities.isRightMouseButton(e)) {
            System.out.println(e.getPoint());
            popUpMenu.setLocation(e.getPoint());
            popUpMenu.setInvoker(popUpMenu);
            popUpMenu.setVisible(true);
        }
    }

    @Override
    public void mousePressed(MouseEvent e) {
        // TODO Auto-generated method stub
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        // TODO Auto-generated method stub
    }

    @Override
    public void mouseEntered(MouseEvent e) {
        // TODO Auto-generated method stub
    }

    @Override
    public void mouseExited(MouseEvent e) {
        // TODO Auto-generated method stub
    }

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

For Full Repo Please Visit Github

Output of above is following

enter image description here

First one, I need some sugessitions to create an algorithm to place the Jpopupmenu in the correct location This one also goin to help to to place undecorated UTILITY JFrame near the Tray Icon.

Second one is how or when the Jpopupmenu shoud be setvisible to false after placing in the location.


Solution

  • You're creating a new JPopupMenu to show on click, but you could instead use the built-in menu for the TrayIcon. It should show in the correct location if you use the PopupMenu instead of the JPopupMenu.

    PopupMenu popup = new PopupMenu();
    TrayIcon trayIcon = new TrayIcon(createImage("images/bulb.gif", "tray icon"));
    MenuItem aboutItem = new MenuItem("About");
    popup.add(aboutItem);
    trayIcon.setPopupMenu(popup);
    

    https://docs.oracle.com/javase/tutorial/uiswing/misc/systemtray.html

    https://docs.oracle.com/javase/7/docs/api/java/awt/TrayIcon.html#setPopupMenu(java.awt.PopupMenu)