¿Cómo posicionar mejor las GUI de Swing?

126

En otro hilo, dije que me gustaba centrar mis GUI haciendo algo como esto:

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

Pero Andrew Thompson tenía una opinión diferente, en lugar de llamar

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

y las mentes inquisitivas quieren saber por qué?

Aerodeslizador lleno de anguilas
fuente
La interfaz gráfica de usuario debe comenzar en el mismo lugar que terminó la última vez.
NomadMaker

Respuestas:

167

En mi opinión, una GUI en el medio de la pantalla se ve tan ... "splash-screen'ish". ¡Sigo esperando que desaparezcan y que aparezca la GUI real !

Desde Java 1.5 hemos tenido acceso a Window.setLocationByPlatform(boolean). cual..

Establece si esta ventana debe aparecer en la ubicación predeterminada para el sistema de ventanas nativo o en la ubicación actual (devuelta por getLocation) la próxima vez que la ventana se haga visible. Este comportamiento se asemeja a una ventana nativa que se muestra sin establecer su ubicación mediante programación. La mayoría de los sistemas de ventanas conectan en cascada las ventanas si sus ubicaciones no están establecidas explícitamente. La ubicación real se determina una vez que la ventana se muestra en la pantalla.

Eche un vistazo al efecto de este ejemplo que coloca 3 GUI en las posiciones predeterminadas elegidas por el sistema operativo: en Windows 7, Linux con Gnome y Mac OS X.

Ventanas apiladas en Windows 7 ingrese la descripción de la imagen aquí Ventanas apiladas en Mac OS X

(3 lotes de) 3 GUI perfectamente apiladas. Esto representa 'la ruta de menor sorpresa' para el usuario final, ya que es cómo el sistema operativo podría colocar 3 instancias del editor de texto plano predeterminado (o cualquier otra cosa, para el caso). Mi agradecimiento a trashgod para Linux y Mac. imágenes

Aquí está el código simple utilizado:

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
fuente
1
@AndrewThompson ¿Por qué su contador es variable en iilugar de solo i? ¿Se adhiere a alguna convención o es una preferencia personal (o tal vez algo completamente diferente)?
MirroredFate
1
@MirroredFate Umm .. Creo que bloquearé la opción 3 allí, "algo completamente diferente". Era justo a lo que me acostumbré cuando programé por primera vez en Basic (sí, hace mucho tiempo). La pereza es la razón del uso continuado, 'si no está roto, no lo arregles'.
Andrew Thompson
1
@MirroredFate ¿Eres por casualidad príncipe de Persia Fan? Lamento mucho ponerlo aquí. No pude resistirme
Anarach
11
@MirroredFate He aquí por qué lo uso en iilugar de i. Cuando participo en concursos de programación, a menudo tengo que buscar el índice de bucle para, por ejemplo, +1o -1desde él para corregirlo por un error. En esos casos, buscar iies mucho más fácil que buscar i, independientemente del editor que use. Del mismo modo, uso jjy kkpara los índices de bucle anidados. :)
musically_ut
5

Estoy totalmente de acuerdo en que setLocationByPlatform(true)es la mejor manera de especificar la posición de un nuevo JFrame, pero en una configuración de monitor doble puede tener problemas. En mi caso, el JFrame secundario aparece en el "otro" monitor. Ejemplo: tengo mi GUI principal en la pantalla 2, inicio un nuevo JFrame con setLocationByPlatform(true)y se abre en la pantalla 1. Así que aquí hay una solución más completa, creo:

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