如何最佳定位Swing GUI界面?

131

另一个线程中,我提到我喜欢通过以下方式使我的GUI居中:

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

但是Andrew Thompson有不同的观点,他建议改为称之为

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

有好奇心的人想知道为什么?


2
GUI应该从上次结束的地方开始。 - NomadMaker
2个回答

173

在我看来,屏幕中央的GUI看起来很像是“启动屏幕”。我一直在等待它们消失,真正的 GUI 出现!

自从Java 1.5以来,我们就可以访问Window.setLocationByPlatform(boolean)。它会:

设置此窗口是否应该出现在本机窗口系统的默认位置或下次使窗口可见时在当前位置(由getLocation返回)。这种行为类似于原生窗口显示而没有通过编程方式设置其位置。 大多数窗口系统如果未明确设置其位置,则级联窗口。实际位置是在窗口显示在屏幕上后确定的。

请查看此示例的效果,它将3个GUI放置在操作系统选择的默认位置上 - 在Windows 7、带有Gnome的Linux和Mac OS X上。

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

3组图形用户界面整齐地堆叠在一起。这代表对最终用户来说“最少惊讶路径”,因为它是操作系统可能放置3个默认纯文本编辑器(或其他任何东西)实例的方式。感谢trashgod提供Linux和Mac图像。

这是使用的简单代码:

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

2
@AndrewThompson 为什么你的计数变量是ii而不是简单的i?这是遵循某种约定还是个人偏好(或者可能完全不同的原因)? - MirroredFate
2
@MirroredFate 嗯...我想我会选择第三个选项,“完全不同的东西”。这是我第一次使用Basic编程时习惯的方式(是的,很久以前)。懒惰是持续使用的原因,“如果它没坏,就不要修理它”。 - Andrew Thompson
1
@MirroredFate 你是波斯王子的粉丝吗?很抱歉在这里提起。我实在忍不住。 - Anarach
14
这是为什么我使用ii而不是i的原因。当我参加编程比赛时,我经常不得不搜索循环索引,例如从中“+1”或“-1”,以修复偏移一个错误。在这些情况下,无论我使用哪个编辑器,搜索ii都比搜索i要容易得多。类似地,我使用jjkk来表示嵌套循环索引。 :) - musically_ut

9

我完全同意使用setLocationByPlatform(true)是指定新的JFrame位置的最好方法,但在双显示器设置中可能会出现问题。在我的情况下,子JFrame会在“另一个”监视器上生成。例如:我将主GUI放在屏幕2上,我使用setLocationByPlatform(true)启动一个新的JFrame,它将在屏幕1上打开。因此,这里有一个更完整的解决方案,我认为:

...
// 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);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接