Question

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.

Was it helpful?

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;

    }
}

OTHER TIPS

What you're trying to do is apparently not possible:

You cannot show the PopupMenu with its show method since you need to specify a JComponent but your TrayIcon isn't one (weird enough though that TrayIcon still manages to do it, so apparently there is a way, don't ask me though..). So, as MadProgrammer suggested, you should try using JPopupMenu instead. Don't add it to your TrayIcon for that won't be possible, but display your JPopupMenu by adding a MouseListener to your TrayIcon. That should do the trick:

final TrayIcon tray = new TrayIcon( img, tooltip, null);
final JPopupMenu menu = new JPopupMenu();
... // your menu initialization.
tray.addMouseListener( new MouseAdapter() {
    @Override
    public void mouseClicked(MouseEvent evt) {
        menu.setLocation( evt.getPoint() );
        menu.setVisible( true );
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top