Comment positionner au mieux les interfaces graphiques Swing?

126

Dans un autre fil, j'ai déclaré que j'aimais centrer mes interfaces graphiques en faisant quelque chose comme ceci:

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

Mais Andrew Thompson avait une opinion différente, appeler à la place

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

et les esprits curieux veulent savoir pourquoi?

Aéroglisseur plein d'anguilles
la source
L'interface graphique doit commencer au même endroit où elle s'est terminée la dernière fois.
NomadMaker

Réponses:

167

À mes yeux, une interface graphique au milieu de l'écran semble tellement .. "splash-screen'ish". J'attends qu'ils disparaissent et que la véritable interface graphique apparaisse!

Depuis Java 1.5, nous avons accès à Window.setLocationByPlatform(boolean). lequel..

Définit si cette fenêtre doit apparaître à l'emplacement par défaut du système de fenêtrage natif ou à l'emplacement actuel (renvoyé par getLocation) la prochaine fois que la fenêtre est rendue visible. Ce comportement ressemble à une fenêtre native affichée sans définir son emplacement par programme. La plupart des systèmes de fenêtrage mettent en cascade les fenêtres si leur emplacement n'est pas défini explicitement. L'emplacement réel est déterminé une fois la fenêtre affichée à l'écran.

Jetez un œil à l'effet de cet exemple qui met 3 interfaces graphiques dans les positions par défaut choisies par le système d'exploitation - sur Windows 7, Linux avec Gnome et Mac OS X.

Windows empilé sur Windows 7 entrez la description de l'image ici Fenêtres empilées sur Mac OS X

(3 lots de) 3 interfaces graphiques parfaitement empilées. Cela représente «le chemin de la moindre surprise» pour l'utilisateur final, car c'est ainsi que le système d'exploitation peut positionner 3 instances de l'éditeur de texte brut par défaut (ou quoi que ce soit d'autre, d'ailleurs). Mes remerciements à trashgod pour Linux et Mac. images.

Voici le code simple utilisé:

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
la source
1
@AndrewThompson Pourquoi votre compteur est-il une variable iiplutôt que juste i? Est-ce que cela adhère à une convention ou est-ce une préférence personnelle (ou peut-être quelque chose de complètement différent)?
MirroredFate
1
@MirroredFate Umm .. Je pense que je vais verrouiller l'option 3 ici, "quelque chose d'entièrement différent". C'était exactement ce à quoi je m'étais habitué lorsque j'ai programmé pour la première fois en Basic (oui, il y a longtemps). La paresse est la raison de l'utilisation continue, «si elle n'est pas cassée, ne la réparez pas».
Andrew Thompson
1
@MirroredFate Êtes-vous par hasard un fan de Prince of Persia? Je suis vraiment désolé de le mettre ici. Je n'ai pas
pu
11
@MirroredFate Voici pourquoi j'utilise à la iiplace de i. Lorsque je participe à des concours de programmation, je dois souvent rechercher l'index de boucle vers, par exemple, +1ou à -1partir de celui-ci pour corriger une erreur. Dans ces cas, la recherche iiest beaucoup plus facile que la recherche i, quel que soit l'éditeur que j'ai utilisé. De même, j'utilise jjet kkpour les index de boucle imbriqués. :)
musicalement_ut
5

Je suis tout à fait d'accord que setLocationByPlatform(true)c'est la meilleure façon de spécifier la position d'un nouveau JFrame, mais sur une configuration à deux moniteurs, vous pouvez avoir des problèmes. Dans mon cas, l'enfant JFrame est engendré sur «l'autre» moniteur. Exemple: j'ai ma GUI principale sur l'écran 2, je démarre un nouveau JFrame avec setLocationByPlatform(true)et il s'ouvre sur l'écran 1. Voici donc une solution plus complète, je pense:

...
// 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
la source