How to best position Swing GUIs?

2018-12-31 00:24发布

In another thread I stated that I liked to center my GUIs by doing something like this:

JFrame frame = new JFrame("Foo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new HexagonGrid());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);

But Andrew Thompson had a different opinion, to instead call

frame.pack();
frame.setLocationByPlatform(true);

and inquiring minds want to know why?

2条回答
旧时光的记忆
2楼-- · 2018-12-31 01:17

To my eye, a GUI in the middle of the screen looks so.. "splash-screen'ish". I keep waiting for them to disappear and the real GUI to appear!

Since Java 1.5 we've had access to Window.setLocationByPlatform(boolean). which..

Sets whether this Window should appear at the default location for the native windowing system or at the current location (returned by getLocation) the next time the Window is made visible. This behavior resembles a native window shown without programmatically setting its location. Most windowing systems cascade windows if their locations are not explicitly set. The actual location is determined once the window is shown on the screen.

Have a look at the effect of this example that puts 3 GUIs into the default positions as chosen by the OS - on Windows 7, Linux with Gnome & Mac OS X.

Stacked windows on Windows 7 enter image description here Stacked windows on Mac OS X

(3 lots of) 3 GUIs neatly stacked. This represents 'the path of least surprise' for the end user, since it is how the OS might position 3 instances of the default plain-text editor (or anything else, for that matter). My thanks to trashgod for the Linux & Mac. images.

Here is the simple code used:

import javax.swing.*;

class WhereToPutTheGui {

    public static void initGui() {
        for (int ii=1; ii<4; ii++) {
            JFrame f = new JFrame("Frame " + ii);
            f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            String s =
                "os.name: " + System.getProperty("os.name") +
                "\nos.version: " + System.getProperty("os.version");
            f.add(new JTextArea(s,3,28));  // suggest a size
            f.pack();
            // Let the OS handle the positioning!
            f.setLocationByPlatform(true);
            f.setVisible(true);
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater( new Runnable() {
            public void run() {
                try {
                    UIManager.setLookAndFeel(
                        UIManager.getSystemLookAndFeelClassName());
                } catch (Exception useDefault) {}
                initGui();
            }
        });
    }
}
查看更多
不流泪的眼
3楼-- · 2018-12-31 01:24

I totally agree that setLocationByPlatform(true) is the nicest way to specify a new JFrame's position but on a dual-monitor setup you can get into issues. In my case, the child JFrame is spawned on 'the other' monitor. Example: I have my main GUI on Screen 2, I start a new JFrame with setLocationByPlatform(true) and it opens on Screen 1. So here is a more complete solution, I think:

        ...
        // Let the OS try to handle the positioning!
        f.setLocationByPlatform(true);
        if( !f.getBounds().intersects(MyApp.getMainFrame().getBounds()) ) {

          // non-cascading, but centered on the Main GUI
          f.setLocationRelativeTo(MyApp.getMainFrame()); 
        }
        f.setVisible(true);
查看更多
登录 后发表回答