saplingPro
saplingPro

Reputation: 21329

Adding JPopupMenu to the TrayIcon

I want to add JPopupMenu to the task bar as a TrayIcon (i.e systemTray.add(trayIcon)) but I haven't found a way to do so.From the docs the constructor of TrayIcon looks like :

public TrayIcon(Image image,
            String tooltip,
            PopupMenu popup)

Is there any way I can do this ?

Upvotes: 16

Views: 6181

Answers (5)

Wing
Wing

Reputation: 1

So excited, I found a solution.The idea is as follows:

  1. TrayIcon trayIcon = new TrayIcon(image, "Tip Text"); // The popup parameter is no longer needed.

  2. trayIcon.addMouseListener(new CustomTrayIconMouseListener());

  3. Class CustomTrayIconMouseListener extends MouseAdapter, and int the TrayIconMouseListener class you need to accomplish two things:

    3.1 Define member variables of type JPopupMenu and do what you want to do, such as adding some JMenuItem and so on.

    3.2 Override mouseClicked method, then pop up the JPopupMenu(setVisible method) by judging the right mouse click event. You need to set its position before popping up JPopupMenu(setLocation method).

Because I also encountered the problem today, I thought of this idea just a moment ago, and I am working hard to solve it now, and I am writing code now. Maybe I will encounterd other problems.

Upvotes: 0

user1941489
user1941489

Reputation:

For the current TrayIcon implementation, it is not possible to directly add a JPopupMenu or JMenu to TrayIcon. However, some people did manage to work around it by implementing a custom MouseListener which listens to right click only at the Trayicon. When the mouse is right-clicked, set location of the Popupmenu at event.getXOnScreen() and event.getYOnScreen() and setvisible it.

Upvotes: 2

Moose Morals
Moose Morals

Reputation: 1648

This is a known problem. There is a bug report, which contains the outline of a workaround. I've adapted that below:

// Build your popup menu
final JPopupMenu trayPopup = new JPopupMenu();
// I'm using actions, there are other ways of doing this.
trayPopup.add(someFantaticAction);

// Get your tray icon
trayIcon = new TrayIcon(icon, "My awesome application");

trayIcon.addMouseListener(new MouseAdapter() {

    @Override
    public void mouseReleased(MouseEvent e) {
        maybeShowPopup(e);
    }

    @Override
    public void mousePressed(MouseEvent e) {
        maybeShowPopup(e);
    }

    private void maybeShowPopup(MouseEvent e) {
        if (e.isPopupTrigger()) {
            trayPopup.setLocation(e.getX(), e.getY());
            trayPopup.setInvoker(trayPopup);
            trayPopup.setVisible(true);
        }
    }
});

Upvotes: 7

mKorbel
mKorbel

Reputation: 109813

I can't see any issues with constructor public TrayIcon(Image image, String tooltip, PopupMenu popup), nor is Java7 on WinXp / Win7 (Win2003/2008)

import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.UIManager;

public class ActiveTray {

    public static void main(String args[]) throws Exception {
        if (SystemTray.isSupported() == false) {
            System.err.println("No system tray available");
            return;
        }
        final SystemTray tray = SystemTray.getSystemTray();
        PropertyChangeListener propListener = new PropertyChangeListener() {

            public void propertyChange(PropertyChangeEvent evt) {
                TrayIcon oldTray[] = (TrayIcon[]) evt.getOldValue();
                TrayIcon newTray[] = (TrayIcon[]) evt.getNewValue();
                System.out.println(oldTray.length + " / " + newTray.length);
            }
        };
        tray.addPropertyChangeListener("trayIcons", propListener);
        Icon icon = new BevelArrowIcon(BevelArrowIcon.UP, false, false);
        Image image = iconToImage(icon);
        PopupMenu popup = new PopupMenu();
        MenuItem item = new MenuItem("Hello, World");
        final TrayIcon trayIcon = new TrayIcon(image, "Tip Text", popup);
        ActionListener menuActionListener = new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                trayIcon.displayMessage("Good-bye", "Cruel World", 
                        TrayIcon.MessageType.WARNING);
            }
        };
        item.addActionListener(menuActionListener);
        popup.add(item);
        ActionListener actionListener = new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                tray.remove(trayIcon);
            }
        };
        trayIcon.addActionListener(actionListener);
        tray.add(trayIcon);
    }

    static Image iconToImage(Icon icon) {
        if (icon instanceof ImageIcon) {
            return ((ImageIcon) icon).getImage();
        } else {
            int w = icon.getIconWidth();
            int h = icon.getIconHeight();
            GraphicsEnvironment ge =
                    GraphicsEnvironment.getLocalGraphicsEnvironment();
            GraphicsDevice gd = ge.getDefaultScreenDevice();
            GraphicsConfiguration gc = gd.getDefaultConfiguration();
            BufferedImage image = gc.createCompatibleImage(w, h);
            Graphics2D g = image.createGraphics();
            icon.paintIcon(null, g, 0, 0);
            g.dispose();
            return image;
        }
    }

    static class BevelArrowIcon implements Icon {

        public static final int UP = 0;         // direction
        public static final int DOWN = 1;
        private static final int DEFAULT_SIZE = 16;
        private Color edge1;
        private Color edge2;
        private Color fill;
        private int size;
        private int direction;

        public BevelArrowIcon(int direction, boolean isRaisedView, 
                boolean isPressedView) {
            if (isRaisedView) {
                if (isPressedView) {
                    init(UIManager.getColor("controlLtHighlight"), 
                            UIManager.getColor("controlDkShadow"), 
                            UIManager.getColor("controlShadow"), 
                            DEFAULT_SIZE, direction);
                } else {
                    init(UIManager.getColor("controlHighlight"), 
                            UIManager.getColor("controlShadow"), 
                            UIManager.getColor("control"), 
                            DEFAULT_SIZE, direction);
                }
            } else {
                if (isPressedView) {
                    init(UIManager.getColor("controlDkShadow"), 
                            UIManager.getColor("controlLtHighlight"), 
                            UIManager.getColor("controlShadow"), 
                            DEFAULT_SIZE, direction);
                } else {
                    init(UIManager.getColor("controlShadow"), 
                            UIManager.getColor("controlHighlight"), 
                            UIManager.getColor("control"), 
                            DEFAULT_SIZE, direction);
                }
            }
        }

        public BevelArrowIcon(Color edge1, Color edge2, Color fill, 
                int size, int direction) {
            init(edge1, edge2, fill, size, direction);
        }

        @Override
        public void paintIcon(Component c, Graphics g, int x, int y) {
            switch (direction) {
                case DOWN:
                    drawDownArrow(g, x, y);
                    break;
                case UP:
                    drawUpArrow(g, x, y);
                    break;
            }
        }

        @Override
        public int getIconWidth() {
            return size;
        }

        @Override
        public int getIconHeight() {
            return size;
        }

        private void init(Color edge1, Color edge2, Color fill, 
                int size, int direction) {
            edge1 = Color.red;
            edge2 = Color.blue;
            this.edge1 = edge1;
            this.edge2 = edge2;
            this.fill = fill;
            this.size = size;
            this.direction = direction;
        }

        private void drawDownArrow(Graphics g, int xo, int yo) {
            g.setColor(edge1);
            g.drawLine(xo, yo, xo + size - 1, yo);
            g.drawLine(xo, yo + 1, xo + size - 3, yo + 1);
            g.setColor(edge2);
            g.drawLine(xo + size - 2, yo + 1, xo + size - 1, yo + 1);
            int x = xo + 1;
            int y = yo + 2;
            int dx = size - 6;
            while (y + 1 < yo + size) {
                g.setColor(edge1);
                g.drawLine(x, y, x + 1, y);
                g.drawLine(x, y + 1, x + 1, y + 1);
                if (0 < dx) {
                    g.setColor(fill);
                    g.drawLine(x + 2, y, x + 1 + dx, y);
                    g.drawLine(x + 2, y + 1, x + 1 + dx, y + 1);
                }
                g.setColor(edge2);
                g.drawLine(x + dx + 2, y, x + dx + 3, y);
                g.drawLine(x + dx + 2, y + 1, x + dx + 3, y + 1);
                x += 1;
                y += 2;
                dx -= 2;
            }
            g.setColor(edge1);
            g.drawLine(xo + (size / 2), yo + size - 1, xo 
                    + (size / 2), yo + size - 1);
        }

        private void drawUpArrow(Graphics g, int xo, int yo) {
            g.setColor(edge1);
            int x = xo + (size / 2);
            g.drawLine(x, yo, x, yo);
            x--;
            int y = yo + 1;
            int dx = 0;
            while (y + 3 < yo + size) {
                g.setColor(edge1);
                g.drawLine(x, y, x + 1, y);
                g.drawLine(x, y + 1, x + 1, y + 1);
                if (0 < dx) {
                    g.setColor(fill);
                    g.drawLine(x + 2, y, x + 1 + dx, y);
                    g.drawLine(x + 2, y + 1, x + 1 + dx, y + 1);
                }
                g.setColor(edge2);
                g.drawLine(x + dx + 2, y, x + dx + 3, y);
                g.drawLine(x + dx + 2, y + 1, x + dx + 3, y + 1);
                x -= 1;
                y += 2;
                dx += 2;
            }
            g.setColor(edge1);
            g.drawLine(xo, yo + size - 3, xo + 1, yo + size - 3);
            g.setColor(edge2);
            g.drawLine(xo + 2, yo + size - 2, xo + size - 1, yo + size - 2);
            g.drawLine(xo, yo + size - 1, xo + size, yo + size - 1);
        }
    }
}

Upvotes: -3

dbow
dbow

Reputation: 665

You can look into Oracle's tutorial and example how to use the system tray

Upvotes: -2

Related Questions