Reputation: 120
I'm able to create a system tray application in Java, but I'm having trouble with positioning. The program will simply need to handle a few inputs/outputs, so I would like it to be easily accessible.
My question is, when I click the system tray icon for my application how can I set it's position elegantly above the system tray? The requirements being that it does this regardless of display settings (resolution, multi monitors, etc) and Taskbar location. Is there a way to tell it to open near the tray, rather than positioning it at all?
I want it to do exactly what the "Network" settings button does in Windows. Similar to the following:
Is this possible in Java?
Upvotes: 2
Views: 2460
Reputation: 347204
As Vulcan has pointed out, yes it's possible.
Also, it's very possible to take into consideration where to place the popup (with relevance to the location where the task icon is)
public class TestTrayIcon {
protected static final PopupFrame POPUP_FRAME = new PopupFrame();
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
TrayIcon trayIcon = new TrayIcon(ImageIO.read(new File("D:/DevWork/common/icons/iconex_v_bundle_png/iconexperience/v_collections_png/basic_foundation/16x16/plain/about.png")));
trayIcon.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
Point pos = e.getLocationOnScreen();
Rectangle screen = getScreenBoundsAt(pos);
if (pos.x + POPUP_FRAME.getWidth() > screen.x + screen.width) {
pos.x = screen.x + screen.width - POPUP_FRAME.getWidth();
}
if (pos.x < screen.x) {
pos.x = screen.x;
}
if (pos.y + POPUP_FRAME.getHeight() > screen.y + screen.height) {
pos.y = screen.y + screen.height - POPUP_FRAME.getHeight();
}
if (pos.y < screen.y) {
pos.y = screen.y;
}
POPUP_FRAME.setLocation(pos);
POPUP_FRAME.setVisible(true);
}
});
SystemTray.getSystemTray().add(trayIcon);
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
}
public static class PopupFrame extends JFrame {
public PopupFrame() throws HeadlessException {
setLayout(new BorderLayout());
add(new JLabel("Hello world"));
pack();
}
}
public static Rectangle getScreenBoundsAt(Point pos) {
GraphicsDevice gd = getGraphicsDeviceAt(pos);
Rectangle bounds = null;
if (gd != null) {
bounds = gd.getDefaultConfiguration().getBounds();
Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gd.getDefaultConfiguration());
bounds.x += insets.left;
bounds.y += insets.top;
bounds.width -= (insets.left + insets.right);
bounds.height -= (insets.top + insets.bottom);
}
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() == 1) {
device = lstDevices.get(0);
}
return device;
}
}
Upvotes: 9
Reputation: 28687
Yes, it is possible.
To set a window's location relative to the lower right corner of the screen, you can get the graphic environment's maximum window bounds and then perform simple math.
Rectangle screen = GraphicsEnvironment.getLocalGraphicsEnvironment()
.getMaximumWindowBounds();
String os = System.getProperty("os.name");
if (os.contains("Windows")) {
setLocation(screen.width - windowSize.width - 6, screen.height - windowSize.height - 6);
} else if (os.contains("Mac")) {
setLocation(screen.width - windowSize.width + 6, 6);
}
The - 6
on both width and height accounts for the small gap between the window and the taskbar, and is easily customizable.
However, with this approach note that Windows taskbars located on the top or left side will still have a taskbar-sized gap on the right/bottom side of the window. I don't believe it is possible to find the taskbar orientation from the Java API alone.
Upvotes: 5