Как лучше всего настроить Swing 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);

Но у Эндрю Томпсона было другое мнение, вместо этого называть

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

и вопрошающие умы хотят знать, почему?

Ответ 1

На мой взгляд, графический интерфейс в середине экрана выглядит так... "splash-screen'ish". Я продолжаю ждать, пока они исчезнут, и появится реальный GUI!

Так как Java 1.5 у нас есть доступ к Window.setLocationByPlatform(boolean). который..

Устанавливает, должно ли это окно отображаться в местоположении по умолчанию для собственной системы окон или в текущем местоположении (возвращенном getLocation), когда следующий раз окно станет видимым. Это поведение похоже на собственное окно, показанное без программной настройки его местоположения. Большинство оконных систем каскадных окон, если их местоположения явно не установлены. Фактическое местоположение определяется после отображения окна на экране.

Посмотрите на эффект этого примера, который помещает 3 графических интерфейса в позиции по умолчанию, выбранные ОС - в Windows 7, Linux с Gnome и Mac OS X.

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

(3 лота) 3 GUIs аккуратно сложены. Это представляет собой "путь наименьшего удивления" для конечного пользователя, так как OS может размещать 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

Я полностью согласен с тем, что setLocationByPlatform(true) - лучший способ указать новую позицию JFrame, но при настройке с двумя мониторами вы можете столкнуться с проблемами. В моем случае ребенок JFrame появляется на "другом" мониторе. Пример: у меня есть основной графический интерфейс на экране 2, я начинаю новый JFrame с setLocationByPlatform(true), и он открывается на экране 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);