Wie positioniere ich Swing GUIs am besten?

126

In einem anderen Thread erklärte ich, dass ich meine GUIs gerne zentrieren würde, indem ich so etwas mache:

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

Aber Andrew Thompson hatte eine andere Meinung, stattdessen anzurufen

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

und fragende Köpfe wollen wissen warum?

Luftkissenfahrzeug voller Aale
quelle
Die GUI sollte an derselben Stelle beginnen, an der sie das letzte Mal endete.
NomadMaker

Antworten:

167

Für mich sieht eine GUI in der Mitte des Bildschirms so aus ... "splash-screen'ish". Ich warte immer darauf, dass sie verschwinden und die echte GUI erscheint!

Seit Java 1.5 haben wir Zugriff auf Window.setLocationByPlatform(boolean). welche..

Legt fest, ob dieses Fenster beim nächsten Anzeigen des Fensters am Standardspeicherort für das native Fenstersystem oder am aktuellen Speicherort (von getLocation zurückgegeben) angezeigt werden soll. Dieses Verhalten ähnelt einem nativen Fenster, das angezeigt wird, ohne dessen Position programmgesteuert festzulegen. Die meisten Fenstersysteme kaskadieren Fenster, wenn ihre Positionen nicht explizit festgelegt sind. Der tatsächliche Standort wird ermittelt, sobald das Fenster auf dem Bildschirm angezeigt wird.

Schauen Sie sich den Effekt dieses Beispiels an, das 3 GUIs an die vom Betriebssystem gewählten Standardpositionen bringt - unter Windows 7, Linux mit Gnome und Mac OS X.

Gestapelte Fenster unter Windows 7 Geben Sie hier die Bildbeschreibung ein Gestapelte Fenster unter Mac OS X.

(3 Lose) 3 GUIs ordentlich gestapelt. Dies stellt für den Endbenutzer den Weg der geringsten Überraschung dar, da das Betriebssystem auf diese Weise möglicherweise 3 Instanzen des Standard-Nur-Text-Editors (oder sonst etwas) positioniert. Mein Dank geht an trashgod für Linux & Mac. Bilder.

Hier ist der einfache verwendete Code:

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
quelle
1
@ AndrewThompson Warum ist Ihre Zählervariable iieher als nur i? Entspricht das einer Konvention oder ist es eine persönliche Präferenz (oder vielleicht etwas ganz anderes)?
MirroredFate
1
@MirroredFate Umm .. Ich denke, ich werde dort Option 3 einschließen, "etwas ganz anderes". Es war genau das, woran ich mich gewöhnt habe, als ich zum ersten Mal in Basic programmiert habe (ja, vor langer Zeit). Faulheit ist der Grund für die weitere Verwendung: "Wenn es nicht kaputt ist, reparieren Sie es nicht."
Andrew Thompson
1
@MirroredFate Bist du zufällig Prinz von Persien Fan? Es tut mir so leid, es hier zu platzieren. Ich konnte einfach nicht widerstehen
Anarach
11
@MirroredFate Hier ist, warum ich iianstelle von verwende i. Wenn ich teilnehmen Wettbewerbe in der Programmierung, muss ich oft für die Loop - Index suchen, sagen wir, +1oder -1von ihr durch einen Fehler beheben ab. In diesen Fällen ist die Suche iiviel einfacher als die Suche i, unabhängig davon, welchen Editor ich verwendet habe. Ebenso verwende ich jjund kkfür die verschachtelten Schleifenindizes. :)
musikalisch_ut
5

Ich stimme voll und ganz zu, dass dies setLocationByPlatform(true)der beste Weg ist, die Position eines neuen JFrames anzugeben, aber bei einem Dual-Monitor-Setup können Probleme auftreten. In meinem Fall wird der untergeordnete JFrame auf dem "anderen" Monitor erzeugt. Beispiel: Ich habe meine Haupt-GUI auf Bildschirm 2, starte einen neuen JFrame mit setLocationByPlatform(true)und er wird auf Bildschirm 1 geöffnet. Hier ist also eine vollständigere Lösung, denke ich:

...
// 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
quelle