设置JFrame位置的最佳实践

18

关于Swing或GUI编程的一个(有点哲学的)问题:是否有公认的最佳实践来确定应用程序中使用的JFrame实例的位置?

  1. 第一个和主要的框架应该放在哪里?总是在中心(setLocationRelativeTo(null))吗?
  2. 子JFrame应该放在哪里?相对于其父JFrame,在屏幕中心,无论我们想要什么位置?

我一直认为有些最佳实践,就像一本“GUI圣经”一样,我错了吗,我应该(吸气)任意决定要做什么?


2
对于第一部分,请参见如何最佳定位Swing GUI。 对于第二部分,我建议仅使用一个框架。 其余的应该是对话框,其位置相对于在 setVisible(true) 上设置的框架的位置设定。 - Andrew Thompson
  1. 你想要去哪里,任何地方都可以。
  2. 对于子窗口,可以查找JDialog或JWindow,并且可以放置在你需要的任何位置。
  3. 由你决定。
- mKorbel
4个回答

25

这里是一个示例,结合了以下建议:

  1. Hovercraft Full Of Eels - 按平台设置位置.

  2. Aardvocate Akintayo Olu - 序列化位置。

但是又增加了两个小改进:

  1. 将宽度/高度也序列化。
  2. 如果在关闭时窗口被最大化,则在获取边界之前还原窗口状态。 (我讨厌那些序列化选项但没有考虑到这一点的应用程序。用户会一直点击“最大化/还原”按钮,并想知道为什么 什么都没发生!)

这4个点结合起来提供了最佳用户体验!

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Properties;
import java.io.*;

class RestoreMe {

    /** This will end up in the current directory
    A more sensible location is a sub-directory of user.home.
    (left as an exercise for the reader) */
    public static final String fileName = "options.prop";

    /** Store location & size of UI */
    public static void storeOptions(Frame f) throws Exception {
        File file = new File(fileName);
        Properties p = new Properties();
        // restore the frame from 'full screen' first!
        f.setExtendedState(Frame.NORMAL);
        Rectangle r = f.getBounds();
        int x = (int)r.getX();
        int y = (int)r.getY();
        int w = (int)r.getWidth();
        int h = (int)r.getHeight();

        p.setProperty("x", "" + x);
        p.setProperty("y", "" + y);
        p.setProperty("w", "" + w);
        p.setProperty("h", "" + h);

        BufferedWriter br = new BufferedWriter(new FileWriter(file));
        p.store(br, "Properties of the user frame");
    }

    /** Restore location & size of UI */
    public static void restoreOptions(Frame f) throws IOException {
        File file = new File(fileName);
        Properties p = new Properties();
        BufferedReader br = new BufferedReader(new FileReader(file));
        p.load(br);

        int x = Integer.parseInt(p.getProperty("x"));
        int y = Integer.parseInt(p.getProperty("y"));
        int w = Integer.parseInt(p.getProperty("w"));
        int h = Integer.parseInt(p.getProperty("h"));

        Rectangle r = new Rectangle(x,y,w,h);

        f.setBounds(r);
    }

    public static void main(String[] args) {
        final JFrame f = new JFrame("Good Location & Size");
        f.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        f.addWindowListener( new WindowAdapter() {
            public void windowClosing(WindowEvent we) {
                try {
                    storeOptions(f);
                } catch(Exception e) {
                    e.printStackTrace();
                }
                System.exit(0);
            }
        });
        JTextArea ta = new JTextArea(20,50);
        f.add(ta);
        f.pack();

        File optionsFile = new File(fileName);
        if (optionsFile.exists()) {
            try {
                restoreOptions(f);
            } catch(IOException ioe) {
                ioe.printStackTrace();
            }
        } else {
            f.setLocationByPlatform(true);
        }
        f.setVisible(true);
    }
}

哇,这是一个非常优雅的答案!谢谢! - Scherrer Vincent
我注意到在具有花哨的视觉图形效果(例如Ubuntu或许多其他Linux系统)的系统上,由于主框架没有立即调整大小,因此需要在f.setExtendedState(Frame.NORMAL)之后立即使用Thread.sleep(1000)。否则,大小和位置将会出现问题。 - dm76
@dm76,谢谢您的信息。也许更安全的做法是启动一个一次性的Swing Timer,设置相同的延迟时间,虽然可能会与关闭进程冲突。1)使用Thread.sleep(n)暂停EDT可能会导致框架保持相同的大小。 - Andrew Thompson
@AndrewThompson,嗯,好观点,我没想到!我会试一下。 - dm76
2
睡眠是否表示需要事件循环进行处理以获取正确的值?如果是这样,那么我们最好在正常情况下缓存高度和宽度,并跳过切换回正常状态。 - Jonathan Seng

9

我通常通过调用平台来决定:

myJFrame.setLocationByPlatform(true);

这个操作使窗口“出现在本机窗口系统的默认位置”。更多信息可参考:Window API


这在Linux或MacOSX上的表现如何? - Stephan
1
你读了我第一条评论中链接的线程吗?它有结果的截图 - Andrew Thompson

2

我通常会从主框架的屏幕中心开始,或者从父级别的中心开始对子框架进行定位,并记录该位置。随后,当用户将框架移动到他们想要的任何位置时,我会记录新位置,并在下次启动应用程序时使用最后的位置来放置框架。


1
不喜欢“center”的第一部分,但在退出时存储位置/在启动时恢复位置(经过一些调整)是很有意义的。 - Andrew Thompson

1

不确定是否存在“最佳实践”,因为这是非常主观的。

将其设置在中心并允许用户更改为他们喜欢的位置似乎是理想的选择。

关于子框架,根据其大小,在父框架的中心或只是一些易于使用的东西。


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