Search code examples
javamouselistenertrayicontray

How do I get a PopupMenu to show up when I left-click on a TrayIcon in Java?


Currently, the PopupMenu will show up when I right-click on the TrayIcon in the SystemTray. However, I want it to do the same when I left-click on the TrayIcon.

I thought I might accomplish this by using a mouseListener on the TrayIcon, but I don't know what method to invoke in the mouseClicked event to achieve the desired results.

icon = new TrayIcon(img, tooltip, popup);

     icon.addMouseListener(
           new MouseAdapter() {
              public void mouseClicked(MouseEvent e) {
                 popup.setEnabled(true);
              }
           });

Using the setEnabled() method does not make the popup menu appear when I left-click the TrayIcon. It actually has no noticeable effect. I'm wondering what method I should use in the mouseClicked() body in order to make the popup show up when it is left-clicked.


Solution

  • Basically, in your mouse listener, you need to determine which button was pressed (and optional, how many times).

    The critical piece of code is this...

    if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 1) { ... }
    

    I've also included some additional code that makes sure the popup does not cover the task bar and is displayed within the viewable area of the screen (it's a nit pick of mine ;))

    public class TestTrayIcon02 {
    
        public static void main(String[] args) {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (Exception ex) {
                    }
                    try {
                        final TrayIcon ti = new TrayIcon(ImageIO.read(getClass().getResource("/Smiley.png")), "Have a nice day");
                        final JPopupMenu popup = new JPopupMenu();
    
                        JMenuItem mi = new JMenuItem("Get me some");
                        mi.addActionListener(new ActionListener() {
                            @Override
                            public void actionPerformed(ActionEvent e) {
                                SystemTray.getSystemTray().remove(ti);
                                System.exit(0);
                            }
                        });
    
                        popup.add(mi);
                        ti.addMouseListener(new MouseAdapter() {
                            @Override
                            public void mouseClicked(MouseEvent e) {
                                if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 1) {
                                    Rectangle bounds = getSafeScreenBounds(e.getPoint());
                                    Point point = e.getPoint();
                                    int x = point.x;
                                    int y = point.y;
                                    if (y < bounds.y) {
                                        y = bounds.y;
                                    } else if (y > bounds.y + bounds.height) {
                                        y = bounds.y + bounds.height;
                                    }
                                    if (x < bounds.x) {
                                        x = bounds.x;
                                    } else if (x > bounds.x + bounds.width) {
                                        x = bounds.x + bounds.width;
                                    }
                                    if (x + popup.getPreferredSize().width > bounds.x + bounds.width) {
                                        x = (bounds.x + bounds.width) - popup.getPreferredSize().width;
                                    }
                                    if (y + popup.getPreferredSize().height > bounds.y + bounds.height) {
                                        y = (bounds.y + bounds.height) - popup.getPreferredSize().height;
                                    }
                                    popup.setLocation(x, y);
                                    popup.setVisible(true);
                                }
                            }
                        });
    
                        SystemTray.getSystemTray().add(ti);
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
            });
        }
    
        public static Rectangle getSafeScreenBounds(Point pos) {
    
            Rectangle bounds = getScreenBoundsAt(pos);
            Insets insets = getScreenInsetsAt(pos);
    
            bounds.x += insets.left;
            bounds.y += insets.top;
            bounds.width -= (insets.left + insets.right);
            bounds.height -= (insets.top + insets.bottom);
    
            return bounds;
    
        }
    
        public static Insets getScreenInsetsAt(Point pos) {
            GraphicsDevice gd = getGraphicsDeviceAt(pos);
            Insets insets = null;
            if (gd != null) {
                insets = Toolkit.getDefaultToolkit().getScreenInsets(gd.getDefaultConfiguration());
            }
            return insets;
        }
    
        public static Rectangle getScreenBoundsAt(Point pos) {
            GraphicsDevice gd = getGraphicsDeviceAt(pos);
            Rectangle bounds = null;
            if (gd != null) {
                bounds = gd.getDefaultConfiguration().getBounds();
            }
            return bounds;
        }
    
        public static GraphicsDevice getGraphicsDeviceAt(Point pos) {
    
            GraphicsDevice device = null;
    
            GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
            GraphicsDevice lstGDs[] = ge.getScreenDevices();
    
            ArrayList<GraphicsDevice> lstDevices = new ArrayList<GraphicsDevice>(lstGDs.length);
    
            for (GraphicsDevice gd : lstGDs) {
    
                GraphicsConfiguration gc = gd.getDefaultConfiguration();
                Rectangle screenBounds = gc.getBounds();
    
                if (screenBounds.contains(pos)) {
    
                    lstDevices.add(gd);
    
                }
    
            }
    
            if (lstDevices.size() > 0) {
                device = lstDevices.get(0);
            } else {
                device = ge.getDefaultScreenDevice();
            }
    
            return device;
    
        }
    }