JDIC Tray Icons
By Eric M. Burke, OCI Principal Software Engineer
May 2005
Introduction
The JDesktop Integration Components (JDIC) project lets portable JavaTM applications access native desktop features. JDIC is a Sun-sponsored open source project currently at release 0.9. When complete, portions of JDIC may eventually become part of J2SE. This article examines the Tray Icon portion of JDIC version 0.9, which lets you create "tray icons" on the native desktop with just a few lines of code.
Our example is a dummy weather forecast service that shows current weather conditions as an animated GIF on the system tray. Balloon help alerts you when a new forecast is available and you can click the icon to view a detailed forecast in a Swing JFrame
.
Installing JDIC
This article was written using version 0.9 of JDIC, available at the JDIC home page. Just follow the links to locate version 0.9, then download the file named jdic-0.9-bin-cross-platform.zip.
Version 0.9 makes installation easier than previous releases. Simply expand the ZIP file and add jdic.jar to your classpath. Since JDIC utilizes native code, running applications is a bit trickier. You must set the java.library.path
system property to your JDIC installation directory. You typically do this with a command-line argument:
java -Djava.library.path=/path/to/jdic/directory MyClassToRun
README.txt
, included in the sample code, contains more detailed information on running the sample application.
The JDIC Tray API
Now let's look at the Tray API in depth. This is a simple API consisting of two classes: SystemTray
and TrayIcon
. These classes are in the org.jdesktop.jdic.tray
package, although this will change when the API becomes part of J2SE. See the references at the end of this article.
SystemTray
has three methods:
static SystemTray getDefaultSystemTray()
- returns the singleton instance of the tray.void addTrayIcon(TrayIcon trayIcon)
- lets you add a new icon to the tray.void removeTrayIcon(TrayIcon trayIcon)
- lets you remove an icon from the tray.
The TrayIcon
class has several methods allowing you to specify the actual icon, include a tooltip, show balloon messages, add a popup JMenu
, and react to a mouse click.
Here is a code snippet for this icon:
- TrayIcon trayIcon = new TrayIcon(icon, caption, popup);
- SystemTray systemTray = SystemTray.getDefaultSystemTray();
- systemTray.addTrayIcon(trayIcon);
That's it! The icon is a normal javax.swing.Icon
object, captionis some text for the icon, and popup is a javax.swing.JPopupMenu
object.
Now let's add a tooltip.
trayIcon.setToolTip(
"Sunday, May 01, 2005 - Thunderstorms (83..89");
It is important to note that the tooltip is a native operating system tooltip. Thus you cannot use HTML as you can in many Swing components. You can, however, include '\n
' characters to generate multi-line tooltips. While this works on Windows XP, the exact behavior is not specified in the JDIC documentation. In other words, this is native code that will behave differently on different platforms. It is probably a good idea to avoid multiline tooltips if you want to maximize portability.
If you do not specify a tooltip, Windows shows the caption as the tooltip. Other platforms may display the caption next to the icon. This behavior is undocumented.
Add a Popup Menu
This next image shows a Swing JPopupMenu
for our tray icon.
You normally specify the popup menu in the TrayIcon
constructor. Or, you can set the menu later:
JPopupMenu popupMenu = ...; // create like normal
trayIcon.setPopupMenu(popupMenu);
Just looking at the popup menu clues you in that this is a Swing component using the default look and feel. You can also use the system look and feel if you want your menus to blend in better. Just put this code in your main()
method:
UIManager.setLookAndFeel(
UIManager.getSystemLookAndFeelClassName());
Because the popup menu is a Swing menu, it supports every feature of Swing menus. This means your menu items can contain graphics, formatting, checkboxes, and separators.
Listen for Clicks
Most tray icons let the user click to view more details or to bring up some kind of configuration window. Our weather forecast icon shows this JFrame
when the user clicks.
This feature is incredibly easy to add. Just register an ActionListener
on the TrayIcon
:
- trayIcon.addActionListener(
- new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- showForecastClicked(); // show the frame
- }
- });
Balloon Messages
JDIC 0.9 adds the ability to show balloon messages from your tray icons.
Here is the code to show the balloon message.
- trayIcon.displayMessage(
- "Important Information",
- "New Forecast Available",
- TrayIcon.INFO_MESSAGE_TYPE);
The following message types are allowed: INFO_MESSAGE_TYPE
, WARNING_MESSAGE_TYPE
, NONE_MESSAGE_TYPE
, and ERROE_MESSAGE_TYPE
. In case you are wondering, that last one should probably be ERROR_MESSAGE_TYPE
, but the JDIC source contains a typo.
As with the tooltip, the balloon message is implemented with native code. You can include newlines on Windows, but the behavior of multiline text is currently undefined. HTML text does not work.
Handling Errors
The weather forecast sample application registers an uncaught exception handler, which is a new Java 5 feature.
- Thread.setDefaultUncaughtExceptionHandler(
- new Thread.UncaughtExceptionHandler() {
- public void uncaughtException(Thread t, Throwable e) {
- e.printStackTrace();
- System.exit(1);
- }
- });
The uncaughtException(...)
method is invoked when a thread terminates due to an exception and no other handler has been defined for that thread. During testing it was discovered that some errors, such as the inability to locate an icon resource, would leave the JRE running indefinitely. Since the icon was not displayed in the tray, the user would have no way of knowing that anything went wrong.
Summary
The tray icon API is very new and currently works on Windows, Solaris, and Linux. A Macintosh version is also in progress. This is "experimental" code, so the API and features may change before the final release.
Interacting with the native operating system desktop is a significant advance for Java applications. As we have seen, the JDIC API is easy to use and lets your Java applications blend in with the desktop better than ever before.
References
- [1] Sample code for this article here
- [2] NOAA XML Weather Feeds - Just in case you want to make a real weather app!
http://weather.gov/alerts/ - [3] The Weather Channel XML Feed - Another XML weather feed.
http://www.weather.com/services/xmloap.html - [4] JDesktop Integration Components (JDIC)
https://jdic.dev.java.net/ - [5] JDIC Issue 220 - discusses plans for including JDIC code with the Mustang J2SE release.
https://jdic.dev.java.net/issues/show_bug.cgi?id=220 - [6] Where's JDIC Going? - A blog entry by George Zhang discussing new features in JDIC 0.9, support for Mac OS X, and plans for J2SE 6.0 (Mustang).
http://weblogs.java.net/blog/georgez/archive/2005/03/wheres_jdic_goi.html - [7] JDIC Features in Mustang - Another blog entry by George Zhang with more detailed plans for Java 6.0 (Mustang).
http://weblogs.java.net/blog/georgez/archive/2005/04/jdic_features_i.html
Software Engineering Tech Trends (SETT) is a regular publication featuring emerging trends in software engineering.