How to spring JFrame from System Tray in Java

故事扮演 提交于 2019-12-08 05:49:07

问题


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?


回答1:


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;
    }
}



回答2:


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.



来源:https://stackoverflow.com/questions/12133273/how-to-spring-jframe-from-system-tray-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!