JFrame y JDialog

De ChuWiki


Cuándo usar JFrame y cuándo JDialog[editar]

En una aplicación java con ventanas debería haber un único JFrame, correspondiente a la ventana principal de la aplicación. El resto de ventanas secundarias deberían ser JDialog.

¿Por qué es esto?

Un JFrame en una ventana que en Windows crea, en la barra de herramientas, donde está el menú de "inicio" y las aplicaciones que tenemos abiertas, un nuevo botón de aplicación abierta. En una aplcación lo normal es que sólo haya un botón ahí. Si creamos varios JFrame en nuestra aplicación, apareceran varios botones, uno por cada JFrame.

El JDialog no muestra este botón. Por ello, el resto de las ventanas de nuestra aplicación deberías ser JDialog.

Hay otro motivo más. Un JFrame no admite a ninguna otra ventana como padre. El JDialog sí admite como padres un JFrame u otros JDialog. Esto es importante porque una ventana hija siempre quedará por encima de su ventana padre. Si al crear los JDialog les pasamos el JFrame como padre, los JDialog siempre estarán visibles por encima del JFrame. No se podrán ir "detrás" de él.

Si además, en el constructor del JDialog ponemos a true el flag que indica que es modal, además de pasarle una ventana padre, entonces el JDialog impedirá el acceso a las otras ventanas hasta que se cierre.

Cambiar el icono de la taza de café en JFrame y JDialog[editar]

Cambiar el icono de la taza de café que aparece en los JFrame, arriba a la izquierda, es fácil. Basta con llamar al método setIconImage() del JFrame.

frame.setIconImage (new ImageIcon("fichero.gif").getImage());

Los JDialog no tienen este método, pero heredan el icono de su ventana padre. Por ello, basta con crearlos pasándoles como padre en el constructor un JFrame que tenga el icono cambiado, o bien otro JDialog que a su vez se le haya cambiado el icono

JDialog dialog = new JDialog (frame);

Abrir y cerrar ventanas secundarias (JDialog) desde la primaria (JFrame)[editar]

En el siguiente código de ejemplo, una ventana principal JFrame tiene un botón para abrir una ventana secundaria JDialog.

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.WindowConstants;

public class DosVentanas {

	private JFrame ventanaPrincipal;
	private JDialog ventanaSecundaria;
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		new DosVentanas();
	}
	
	public DosVentanas()
	{
		// Construcción de ventana principal
		ventanaPrincipal = new JFrame("Ventana principal");
		JButton boton = new JButton("Abre secundaria");
		ventanaPrincipal.getContentPane().add(boton);
		ventanaPrincipal.pack();
		
		// Construcción de ventana secundaria
		ventanaSecundaria = new JDialog(ventanaPrincipal,"Ventana secundaria");
		JLabel etiqueta = new JLabel("Hola");
		ventanaSecundaria.getContentPane().add(etiqueta);
		ventanaSecundaria.pack();

		// Hacer que el botón abra la ventana secundaria y cierre la
		// principal
		boton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				ventanaPrincipal.setVisible(false);
				ventanaSecundaria.setVisible(true);
			}
		
		});
		
		// Hacer que al cerrarse la secundaria con la x de arriba a la
		// derecha, se muestre la primaria
		ventanaSecundaria.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				ventanaPrincipal.setVisible(true);
				ventanaSecundaria.setVisible(false);
			}
		
			public void windowClosed(WindowEvent e) {
				ventanaPrincipal.setVisible(true);
				ventanaSecundaria.setVisible(false);
			}
		});
		
		// Mostrar la ventana principal
		ventanaPrincipal.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		ventanaPrincipal.setVisible(true);
	}

}

En primer lugar se construyen la ventana primaria y secundaria, una con un botón y la otra con una etiqueta.

Luego al botón se le añade un ActionListener para que oculte la principal y muestre la secundaria cuando se pulsa.

Finalmente se añade un WindowAdapter a la ventana secundaria para enterarnos de cuándo se cierra pulsando la x de arriba a la derecha. Cuando esto sucede, mostramos la ventana primaria y ocultamos la secundaria.

Centrar una ventana en pantalla[editar]

Si queremos que una ventana nos salga centrada en la pantalla, antes del jdk 1.4 no nos quedaba más remedio que echar unas cuentas. El código podía ser como este:

        // Se da a la ventana el tamaño, con pack() o setSize()
        v.pack();

        // Se obtienen las dimensiones en pixels de la pantalla.
        Dimension pantalla = Toolkit.getDefaultToolkit().getScreenSize();
        
        // Se obtienen las dimensiones en pixels de la ventana.
        Dimension ventana = v.getSize();
        
        // Una cuenta para situar la ventana en el centro de la pantalla.
        v.setLocation(
            (pantalla.width - ventana.width) / 2,
            (pantalla.height - ventana.height) / 2);
        
        // Se visualiza la ventana.
        v.setVisible(true);

Para que el método pack() dé un tamaño adecuado a la ventana es necesario que la ventana ya tenga dentro los componentes y que estemos usando un Layout que no sea null.

Desde la versión 1.4 del JDK existe un método de la clase JWindow que realiza la operación de centrar la ventana sobre otro componente especifico. Este método es setLocationRealtiveTo(JComponenet otroComponente), donde otroComponente es cualquier componente sobre el que queremos que salga centrada la ventana p.e: JFrame, JDialog, JButton, JTextField, etc...

 // La ventana saldrá centrada sobre el botón unBoton.
 v.setLocationRelativeTo (unBoton);

Si se pasa null como valor a este parámetro, entonces la ventana se centrara justo al centro de la pantalla del PC...

 // La ventana saldrá centrada en pantalla.
 v.setLocationRelativeTo (null);