web-dev-qa-db-fra.com

Comment positionner au mieux les interfaces graphiques Swing?

Dans n 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, pour appeler à la place

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

et les esprits curieux veulent savoir pourquoi?

124

À mon avis, une interface graphique au milieu de l'écran a l'air si .. "splash-screen'ish". J'attends qu'ils disparaissent et que l'interface graphique réelle apparaisse!

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

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 créent des fenêtres en cascade si leur emplacement n'est pas défini explicitement. L'emplacement réel est déterminé une fois que la fenêtre est affichée à l'écran.

Jetez un œil à l'effet de cet exemple qui place 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.

Stacked windows on Windows 7enter image description hereStacked windows on Mac OS X

(3 lots de) 3 interfaces graphiques bien 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 toute autre chose, d'ailleurs). Merci à 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();
            }
        });
    }
}
165
Andrew Thompson

Je suis tout à fait d'accord que setLocationByPlatform(true) est la meilleure façon de spécifier la position d'un nouveau JFrame mais sur un configuration double moniteur vous pouvez rencontrer des problèmes. Dans mon cas, l'enfant JFrame est généré sur "l'autre" moniteur. Exemple: J'ai mon interface graphique 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);
5
Axel Podehl