Comment mieux positionner les interfaces graphiques Swing?

Dans un autre sujet, 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 un avis différent, à la place d’appeler

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

et les esprits curieux veulent savoir pourquoi?

À mon avis, une interface graphique au milieu de l’écran a l’air si .. “écran de démarrage”. Je continue à attendre leur disparition et la vraie interface graphique à apparaître!

Depuis Java 1.5, nous avons access à 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 explicitement défini. L’emplacement réel est déterminé une fois que la fenêtre est affichée à l’écran.

Jetez un coup d’oeil à l’effet de cet exemple qui place 3 interfaces graphiques dans les positions par défaut choisies par le système d’exploitation – sous Windows 7, Linux avec Gnome et Mac OS X.

Windows empilé sur Windows 7entrer la description de l'image iciFenêtres empilées sur Mac OS X

(3 lots de) 3 interfaces graphiques soigneusement 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 en clair par défaut (ou toute autre chose). 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(); } }); } } 

Je suis totalement d’accord sur le fait que setLocationByPlatform(true) est la meilleure façon de spécifier la position d’un nouveau JFrame, mais sur une configuration à deux moniteurs, vous pouvez entrer dans 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 lance 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);