 |
Using JPopupMenu in TrayIcon
Posted by ixmal on May 04, 2006 at 05:23 AM | Comments (18)
What's the problem?
Tray icons introduced in Mustang have several properties and methods corresponding to image for the icon, tooltip text, popup menu and ability to show some message to the user. Let's inspect the popup menu more closely.
Popup menu used in tray icons must be an instance of java.awt.PopupMenu. This class represents a menu and allows to insert or delete simple menu items and separators. You cannot change its appearance or even provide an image for particular menu item.
Use JPopupMenu instead
There is another class to create popup menus provided by Swing: javax.swing.JPoupMenu. As all Swing components this class can be customized in any way and makes use of the current Look&Feel. Here is a short illustrating example how it can be used:
First, create a tray icon with a null popup since we're going to use our own one:
TrayIcon trayIcon = new TrayIcon(someImage, "Tooltip", null);
Then, create a custom JPopupMenu:
JPopupMenu jpopup = new JPopupMenu();
JMenuItem javaCupMI = new JMenuItem("Example", new ImageIcon("javacup.gif"));
jpopup.add(javaCupMI);
jpopup.addSeparator();
JMenuItem exitMI = new JMenuItem("Exit");
jpopup.add(exitMI);
At last, show the popup menu when user clicks a right mouse button on the tray icon:
trayIcon.addMouseListener(new MouseAdapter() {
public void mouseReleased(MouseEvent e) {
if (e.isPopupTrigger()) {
jpopup.setLocation(e.getX(), e.getY());
jpopup.setInvoker(jpopup);
jpopup.setVisible(true);
}
}
});
And enjoy the result:
Magic?
You may probably ask me: "What is that magic line 'jpopup.setInvoker(jpopup);' for?" The answer is not as simple as quiestion is, though.
JavaDoc for JPopupMenu.setInvoker() method says that invoker is the component in which the popup menu menu is to be displayed. This property can be set to null, but it leads to popup menu to operate incorrectly.
Setting popup's invoker to itself has some side-effect too. Usually, if you dispose all the windows in your application, Java exits automatically. If you show JPopupMenu with self invoker, it won't, so the only way to terminate the whole application is to call to System.exit().
Both of these issues are well known to Swing team and will be corrected before the Mustang final release. See 6421284 and 6400183 for details.
Bookmark blog post: del.icio.us Digg DZone Furl Reddit
Comments
Comments are listed in date ascending order (oldest first) | Post Comment
-
I saw a question about this in the forums awhile back, remarkable your solution looks fairly simple.
leouser
Posted by: leouser on May 04, 2006 at 06:29 AM
-
Could you post a link to the forum where this problem was discussed and their solution, please?
Posted by: ixmal on May 04, 2006 at 06:56 AM
-
Ill have to do some digging, but I don't think they came up with a solution. It was more of a "hey why can't we use a JPopupMenu with the TrayIcon" kind of thread. I remember speculating on a possibility, but I like your idea better.
leouser
Posted by: leouser on May 04, 2006 at 08:05 AM
-
It was this thread: http://forums.java.net/jive/thread.jspa?threadID=14279&tstart=30
and as I said, no real solutions presented.
leouser
Posted by: leouser on May 04, 2006 at 08:08 AM
-
This is not enough!
The JPopupMenu should be poping up on top of the taskbar, as native popups do.
Posted by: cowwoc on May 05, 2006 at 08:06 AM
-
Please vote for http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6285881 to fix this problem.
Posted by: cowwoc on May 05, 2006 at 08:12 AM
-
I tried under Linux and Netbeans 5.0. Works OK but got :
java.lang.ClassCastException: java.awt.TrayIcon cannot be cast to java.awt.Component
Posted by: dags on May 05, 2006 at 10:10 AM
-
Thanks, dags, I have just got the exception. I think somewhere in the AWT/Swing code all the mouse events are supposed to be sent for Components, but TrayIcon is not a descendant of Component:( I will file a new bug about this.
Posted by: ixmal on May 06, 2006 at 12:56 AM
-
- When I use PopupMenu with TrayIcon then I cannot use Unicode but I can close popup that don't need click on its menuitems.
- When I use JPopupMenu with TrayIcon then I can use Unicode but I can't close popup, I only close this popup when I click on its menuitems.
Posted by: phubinh13 on October 26, 2006 at 11:43 PM
-
- When I use PopupMenu with TrayIcon then I cannot use Unicode but I can close popup that don't need click on its menuitems.
- When I use JPopupMenu with TrayIcon then I can use Unicode but I can't close popup, I only close this popup when I click on its menuitems.
Posted by: phubinh13 on October 26, 2006 at 11:46 PM
-
I am using the final release of JDK 1.6.0 and I am still getting the java.lang.ClassCastException: java.awt.TrayIcon cannot be cast to java.awt.Component error. Any luck or workarounds for this? I really prefer to use a Swing Jpopupmenu to a regular menu because I am using a javax.swing.Action framework and i don't see any way to use Actions in regular java.awt.PopupMenu's. Hope there is some workaround!
Posted by: elefkof on December 27, 2006 at 10:24 AM
-
Hi... I also get the "java.awt.TrayIcon cannot be cast to java.awt.Component" error. Please tell me what to do...
Posted by: geertjan on February 23, 2007 at 10:32 AM
-
Hello. I can make JPopupWindow above MS-Windows task bar ( SwingUtilities.windowForComponent( JPupupMenu ).window.setAlwaysOnTop( true ) ) , but how to get keyboard focus/input ????
Looking back to normal PopupMenu ... when it is pop up -> it blocks Event Dispatch Thread (EDT) (even if I fire it manually .show() from new Thread , I also tryed install new EventQueue ).
I spent last 10 days to solwe those problems, no success :(((((.
Posted by: kermitas on February 24, 2007 at 03:44 AM
-
Like kermitas, I can get JPopupMenu to show on top of taskbar, but I cannot make it go away (dismiss) if click on anywhere except on my Java app frame and on JPopupMenu itself.
The java.lang.ClassCastException happens if user invoke the popup again when the it is already visible (but maybe hidden behind other windows).
For popup location, I prefer popping it higher :
popupmenu.setLocation(e.getX(), e.getY()-popupmenu.getPreferredSize().height);
I guess until Sun fixes the 'java.lang.ClassCastException' bug, I will go back to using jeans' TrayIcon (http://jeans.studentenweb.org/java/trayicon/trayicon.html)
Posted by: pk_thoo on March 15, 2007 at 06:55 AM
-
One more thing, self invoking doesn't work on at least 2 LAF packs : SkinLF and Substance. You'll get StackOverflow error.
Posted by: pk_thoo on March 16, 2007 at 01:30 AM
-
Hello,
i think i wrote some example on how to fix all that issues, Also my impl. fly over the taskbar.
Take a look at (Forum is german): Swing Based Tray Icon with Java 6
- Jens
Posted by: mac_systems on November 29, 2007 at 08:18 AM
-
Try this ugly hack to fix a problem with exceptions:
Toolkit.getDefaultToolkit().getSystemEventQueue().push( new PopupFixQueue(jpopup) );
...
public class PopupFixQueue extends EventQueue {
private JPopupMenu popup;
public PopupFixQueue(JPopupMenu popup) {
this.popup = popup;
}
protected void dispatchEvent(AWTEvent event) {
try {
super.dispatchEvent(event);
} catch (Exception ex) {
if (event.getSource() instanceof TrayIcon) {
popup.setVisible(false);
}
}
}
}
Posted by: nick_fedorov on March 18, 2008 at 12:52 AM
-
@nick_fedorov Thankyou thankyou thankyou thankyou.... This fix worked a charm, and moreover, I can see why it works as well. The best kinds of fix!
Posted by: davyboyhayes on March 31, 2008 at 03:28 PM
|