Recommended: Sing it, brah! 5 fabulous songs for developers
JW's Top 5
by John Zukowski
The Java SE 6 release introduced several new capabilities to the Abstract Window Toolkit (AWT). Users are no longer limited to Swing and enhancing the graphical user interface (GUI) components. With Java SE 6, you have new access to things such as desktop applications through what used to be called the JDesktop Integration Components (JDIC), described in a previous tip: Communicating With Native Applications Using JDIC. Although its package changed to just java.awt, the API remains much as described in that tip. You also now have the ability to add applications to the Microsoft Windows taskbar, the Gnome notification area, or KDE's system tray. That is what this tip is all about.
Access to the system tray requires only two new classes: SystemTray to represent the desktop's system tray and TrayIcon for its icon. Why not use Image or Icon for that? TrayIcon has an attached PopupMenu and tool tip text. Here's how all the pieces fit together.
The SystemTray class builds on the concept of the platform having a single instance of the tray. Calling the getSystemTray() method of SystemTray will return that instance. But some platforms might not support a system tray, so it is best to check first through the isSupported() method. Otherwise, an UnsupportedOperationException will be thrown if the platform does not support a system tray. Here's the typical pattern you'll need for acquiring that system tray instance:
if (SystemTray.isSupported()) {
SystemTray tray = SystemTray.getSystemTray();
}
Most of the common platforms -- Microsoft Windows, Solaris Operating System, and Linux -- will support a system, but some platforms may not.
After getting the SystemTray, TrayIcon comes into play. You get to add one or more of those to the tray, one for each menu and tool tip you wish to add, with of course an Image.
Getting started with a basic framework to use SystemTray gives you the following program. The program puts a single TrayIcon on the SystemTray with a single MenuItem on its PopupMenu. In the installed JDK directory, there is a demo subdirectory. You can get an icon from that subdirectory. Any supported format will do.
import javax.swing.*;
import java.awt.*;
public class BasicTray {
public static void main(String args[]) {
Runnable runner = new Runnable() {
public void run() {
if (SystemTray.isSupported()) {
SystemTray tray = SystemTray.getSystemTray();
Image image = Toolkit.getDefaultToolkit().getImage("gifIcon.gif");
PopupMenu popup = new PopupMenu();
MenuItem item = new MenuItem("A MenuItem");
popup.add(item);
TrayIcon trayIcon = new TrayIcon(image, "The Tip Text", popup);
try {
tray.add(trayIcon);
} catch (AWTException e) {
System.err.println("Can't add to tray");
}
} else {
System.err.println("Tray unavailable");
}
}
};
EventQueue.invokeLater(runner);
}
}
Resting your mouse over the icon shows the tool tip text. Clicking the icon pops the menu up, showing the menu item. Had there been an Action/ActionListener added to the MenuItem, it would have been activated upon selection.
Besides the ability to create a big frame for your application when you select the menu item, one other important method of TrayIcon is worth mentioning: displayMessage(). Calling this method will show a pop-up message near the icon on the system tray. The method takes three arguments: the title for the pop-up window, which can be null; the message itself; and a MessageType to indicate the type of message. Valid types are ERROR, WARNING, INFO, or NONE. All but NONE have their own icon added to the pop-up window. The icon is a smaller version of the one shown in a JOptionPane.
The following program adds a few more menu items to the earlier example to demonstrate the displayMessage() method and all its message types. The final menu item with Close uses the remove() method of SystemTray to remove the TrayIcon from the SystemTray and shuts down.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class FullTray {
static class ShowMessageListener implements ActionListener {
TrayIcon trayIcon;
String title;
String message;
TrayIcon.MessageType messageType;
ShowMessageListener(
TrayIcon trayIcon,
String title,
String message,
TrayIcon.MessageType messageType) {
this.trayIcon = trayIcon;
this.title = title;
this.message = message;
this.messageType = messageType;
}
public void actionPerformed(ActionEvent e) {
trayIcon.displayMessage(title, message, messageType);
}
}
public static void main(String args[]) {
Runnable runner = new Runnable() {
public void run() {
if (SystemTray.isSupported()) {
final SystemTray tray = SystemTray.getSystemTray();
Image image = Toolkit.getDefaultToolkit().getImage("gifIcon.gif");
PopupMenu popup = new PopupMenu();
final TrayIcon trayIcon = new TrayIcon(image, "The Tip Text", popup);
MenuItem item = new MenuItem("Error");
item.addActionListener(new ShowMessageListener(trayIcon,
"Error Title", "Error", TrayIcon.MessageType.ERROR));
popup.add(item);
item = new MenuItem("Warning");
item.addActionListener(new ShowMessageListener(trayIcon,
"Warning Title", "Warning", TrayIcon.MessageType.WARNING));
popup.add(item);
item = new MenuItem("Info");
item.addActionListener(new ShowMessageListener(trayIcon,
"Info Title", "Info", TrayIcon.MessageType.INFO));
popup.add(item);
item = new MenuItem("None");
item.addActionListener(new ShowMessageListener(trayIcon,
"None Title", "None", TrayIcon.MessageType.NONE));
popup.add(item);
item = new MenuItem("Close");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
tray.remove(trayIcon);
}
});
popup.add(item);
try {
tray.add(trayIcon);
} catch (AWTException e) {
System.err.println("Can't add to tray");
}
} else {
System.err.println("Tray unavailable");
}
}
};
EventQueue.invokeLater(runner);
}
}
Compile and run the program to have the tray icon added to the system tray. On a Microsoft Windows box, you'll need to right click on the icon to see the pop-up menu. Select each icon to see each message displayed, and select Close when you are done. Removing the tray icon essentially causes the event dispatch thread to end, allowing the program to exit.
*******
jMaki is a lightweight framework that makes it easy to build Ajax-based web applications. Learn more in this Deep Dive with jMaki Project lead, Greg Murray.
*******