Як найкраще позиціонувати інтерфейси Swing?


126

В іншій темі я заявив, що мені подобається зосереджувати свої графічні інтерфейси, роблячи щось подібне:

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

і допитливі розуми хочуть знати, чому?


Гуй повинен починатися там же, де він закінчувався минулого разу.
NomadMaker

Відповіді:


167

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

З Java 1.5 ми мали доступ до Window.setLocationByPlatform(boolean). котрий..

Встановлює, чи має це вікно відображатися у стандартному розташуванні для рідної системи вікон або у поточному місці (повертається getLocation) наступного разу, коли вікно стане видимим. Така поведінка нагадує рідне вікно, показане без програмного встановлення його місця розташування. Більшість систем вікон каскадують вікна, якщо їх місця не встановлені явно. Фактичне розташування визначається, коли вікно відображається на екрані.

Подивіться на ефект цього прикладу, який ставить 3 графічні інтерфейси у положення за замовчуванням, як вибрано ОС - у Windows 7, Linux та Gnome & Mac OS X.

Складені вікна в Windows 7 введіть тут опис зображення Складені вікна на Mac OS X

(3 лоти) 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();
            }
        });
    }
}

1
@AndrewThompson Чому ваша змінна лічильник, iiа не просто i? Це дотримується якоїсь конвенції чи це особисті переваги (чи, можливо, щось зовсім інше)?
MirroredFate

1
@MirroredFate Umm .. Я думаю, я заблокую варіант 3 там "щось зовсім інше". Це було саме те, до чого я звик, коли вперше запрограмував у Basic (так, давно). Лінь - це причина для подальшого використання, "якщо вона не зламалася, не виправляйте".
Ендрю Томпсон

1
@MirroredFate Чи є у вас випадковий принц Персії Фана? Мені дуже шкода, що це тут. Я просто не міг протистояти
Анарах

11
@MirroredFate Ось чому я використовую iiзамість цього i. Коли я беру участь у змаганнях з програмування, мені часто доводиться шукати індекс циклу, скажімо, +1або -1з нього, щоб виправити одну помилку. У таких випадках пошук iiнабагато простіше, ніж пошук i, незалежно від того, який редактор я використовував. Аналогічно я використовую jjі kkдля вкладених індексів циклу. :)
musically_ut

5

Я повністю погоджуюся, що 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);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.