Jak najlepiej ustawić Swing GUI?

126

W innym wątku stwierdziłem, że lubię wyśrodkować moje GUI, robiąc coś takiego:

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

Ale Andrew Thompson miał inne zdanie, zamiast tego zadzwonić

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

a dociekliwe umysły chcą wiedzieć, dlaczego?

Poduszkowiec pełen węgorzy
źródło
Interfejs GUI powinien rozpocząć się w tym samym miejscu, w którym zakończył się ostatnim razem.
NomadMaker

Odpowiedzi:

167

Dla mnie GUI na środku ekranu wygląda tak… „splash-screen'ish”. Czekam, aż znikną i pojawi się prawdziwy GUI!

Od Java 1.5 mamy dostęp do Window.setLocationByPlatform(boolean). który..

Ustawia, czy to okno powinno pojawić się w domyślnej lokalizacji dla natywnego systemu okienkowego, czy w bieżącej lokalizacji (zwróconej przez getLocation) następnym razem, gdy okno stanie się widoczne. To zachowanie przypomina natywne okno wyświetlane bez programowego ustawiania jego lokalizacji. Większość systemów okienkowych tworzy kaskadę okien, jeśli ich położenie nie jest wyraźnie określone. Rzeczywista lokalizacja jest określana po wyświetleniu okna na ekranie.

Spójrz na efekt tego przykładu, który ustawia 3 GUI w domyślnych pozycjach wybranych przez system operacyjny - na Windows 7, Linux z Gnome i Mac OS X.

Ułożone okna w systemie Windows 7 wprowadź opis obrazu tutaj Ułożone okna w systemie Mac OS X

(3 partie) 3 starannie ułożone GUI. Stanowi to „ścieżkę najmniejszego zaskoczenia” dla użytkownika końcowego, ponieważ w ten sposób system operacyjny może umieścić 3 wystąpienia domyślnego edytora zwykłego tekstu (lub cokolwiek innego, jeśli o to chodzi). Dziękuję trashgod za Linuksa i Maca. zdjęcia.

Oto zastosowany prosty kod:

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
źródło
1
@AndrewThompson Dlaczego zmienna licznika jest iiraczej zmienna i? Czy jest to zgodne z jakąś konwencją, czy jest to osobiste preferencje (a może coś zupełnie innego)?
MirroredFate
1
@MirroredFate Umm .. Myślę, że zablokuję tam opcję 3, „coś zupełnie innego”. Właśnie do tego przywykłem, kiedy po raz pierwszy programowałem w Basicu (tak, dawno temu). Lenistwo to powód dalszego używania, „jeśli się nie zepsuł, nie naprawiaj go”.
Andrew Thompson,
1
@MirroredFate Czy przypadkiem jesteś fanem księcia perskiego? Tak mi przykro, że to tutaj umieszczam. Po prostu nie mogłem się oprzeć
Anarach
11
@MirroredFate Oto dlaczego używam iizamiast i. Kiedy biorę udział w konkursach programowania, często trzeba szukać indeksu pętli do, powiedzmy, +1lub -1z niej naprawić off by one. W takich przypadkach wyszukiwanie iijest znacznie łatwiejsze niż wyszukiwanie i, niezależnie od używanego edytora. Podobnie używam jji kkdla indeksów zagnieżdżonych pętli. :)
musically_ut
5

Całkowicie się zgadzam, że setLocationByPlatform(true)jest to najładniejszy sposób określenia nowej pozycji JFrame, ale w konfiguracji z dwoma monitorami możesz mieć problemy. W moim przypadku podrzędna ramka JFrame jest generowana na „drugim” monitorze. Przykład: Moje główne GUI jest na ekranie 2, zaczynam nową ramkę JFrame setLocationByPlatform(true)i otwiera się ona na ekranie 1. Tak więc myślę, że tutaj jest bardziej kompletne rozwiązanie:

...
// 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);
Axel Podehl
źródło