131

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?

Community
  • 1
  • 1
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373

2 Answers2

173

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();
            }
        });
    }
}
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • 2
    @AndrewThompson Why is your counter variable `ii` rather than just `i`? Does that adhere to some convention or is it a personal preference (or maybe something entirely different)? – MirroredFate Mar 26 '14 at 22:02
  • 2
    @MirroredFate Umm.. I think I'll lock in option 3 there, "something entirely different". It was just what I got used to when I first programmed in Basic (yes, a long time ago). Laziness it the reason for continued use, 'if it ain't broke, don't fix it'. – Andrew Thompson Mar 27 '14 at 03:32
  • 1
    @MirroredFate Are you by any chance prince of persia Fan? I am so sorry to put it here. I just couldnt resist – Anarach Aug 24 '15 at 14:16
  • 14
    @MirroredFate Here's why I use `ii` instead of `i`. When I take part in programming competitions, I often have to search for the loop index to, say, `+1` or `-1` from it to fix off by one errors. In those cases, searching for `ii` is much easier than searching for `i`, regardless of which editor I used. Similarly, I use `jj` and `kk` for the nested loop indexes. :) – musically_ut Aug 24 '15 at 22:09
9

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);
Miss Chanandler Bong
  • 4,081
  • 10
  • 26
  • 36
Axel Podehl
  • 4,034
  • 29
  • 41