Come posizionare al meglio le GUI di Swing?


126

In un altro thread ho affermato che mi piaceva centrare le mie GUI facendo qualcosa del genere:

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

Ma Andrew Thompson ha avuto un'opinione diversa, invece di chiamare

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

e le menti indagatrici vogliono sapere perché?


La GUI dovrebbe iniziare nello stesso posto in cui è terminata l'ultima volta.
NomadMaker

Risposte:


167

A mio avviso, una GUI al centro dello schermo sembra così ... "splash-screen'ish". Continuo ad aspettare che scompaiano e appaia la vera GUI!

Da Java 1.5 abbiamo avuto accesso a Window.setLocationByPlatform(boolean). quale..

Imposta se questa finestra deve apparire nella posizione predefinita per il sistema di finestre nativo o nella posizione corrente (restituita da getLocation) alla successiva visualizzazione della finestra. Questo comportamento ricorda una finestra nativa mostrata senza impostarne programmaticamente la posizione. La maggior parte dei sistemi di finestre a cascata le finestre se le loro posizioni non sono impostate in modo esplicito. La posizione effettiva viene determinata una volta visualizzata la finestra sullo schermo.

Dai un'occhiata all'effetto di questo esempio che mette 3 GUI nelle posizioni predefinite scelte dal sistema operativo: su Windows 7, Linux con Gnome e Mac OS X.

Finestre impilate su Windows 7 inserisci qui la descrizione dell'immagine Finestre impilate su Mac OS X

(3 lotti di) 3 GUI ordinatamente impilate. Questo rappresenta "il percorso di minor sorpresa" per l'utente finale, poiché è il modo in cui il sistema operativo può posizionare 3 istanze dell'editor di testo normale predefinito (o qualsiasi altra cosa, del resto). I miei ringraziamenti a trashgod per Linux e Mac. immagini.

Ecco il semplice codice utilizzato:

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 Perché la tua contro variabile è iipiù che semplice i? Aderisce a qualche convenzione o è una preferenza personale (o forse qualcosa di completamente diverso)?
MirroredFate

1
@MirroredFate Umm .. Penso che bloccherò l'opzione 3 lì, "qualcosa di completamente diverso". Era proprio quello a cui mi ero abituato quando ho programmato per la prima volta in Basic (sì, molto tempo fa). La pigrizia è la ragione per cui è continuato l'uso, "se non è rotto, non aggiustarlo".
Andrew Thompson,

1
@MirroredFate Sei per caso un principe della Persia Fan? Mi dispiace tanto metterlo qui. Non ho potuto resistere
Anarach il

11
@MirroredFate Ecco perché lo uso iiinvece di i. Quando prendo parte a concorsi di programmazione, spesso devo cercare l'indice del loop, per esempio, +1o -1da esso per correggere con un errore. In questi casi, la ricerca iiè molto più semplice della ricerca i, indipendentemente dall'editor che ho usato. Allo stesso modo, io uso jje kkper gli indici di loop nidificati. :)
musically_ut,

5

Sono totalmente d'accordo sul fatto che setLocationByPlatform(true)sia il modo migliore per specificare la posizione di un nuovo JFrame, ma su una configurazione a doppio monitor è possibile riscontrare problemi. Nel mio caso, il bambino JFrame viene generato sul monitor "l'altro". Esempio: ho la mia GUI principale sullo schermo 2, inizio un nuovo JFrame setLocationByPlatform(true)e si apre sullo schermo 1. Quindi ecco una soluzione più completa, penso:

...
// 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);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.