23 enero 2006

Cuando me meten en una ventana

Con relativa frecuencia hago clases que heredan de JButton, por ejemplo, MiBoton. Esta clase MiBoton ya tiene implementado el código que debe ejecutarse al apretar el botón y es un código más o menos reutilizable en varios sitios (por eso el hacer el botón en concreto).

A veces ese botón necesita abrir una pequeña ventana secundaria (una ventana de confirmación, para introducir algunos datos o lo que sea). Esa ventana, para que todo cuadre como debe ser, debe ser un JDialog cuyo padre sea la ventana (JFrame o JDialog) que contiene al botón, de esta forma el dialogo que abramos no saldrá detrás de la ventana que contiene al botón. Y ahí viene el problema. Cuando se hace el código del botón más o menos genérico, no se dispone de la ventana que contiene el botón. De hecho, si el botón está en una especie de librería, no se sabe quién lo va a utilizar ni en qué ventana lo va a poner.

La solución que le he dado a este problema, es crear un HierarchyListener. El botón se suscribe a un cambio en la jerarquía de padres de él mismo. De esta forma, cuando el botón se añade a un panel o ese panel se añade a una ventana, el botón se entera. Con cada cambio de jerarquía, se intenta obtener la ventana padre del botón, utilizando el método SwingUtilities.getWindowAncestor(). En el momento que este método nos devuelva una ventana, esta será la ventana que contiene al botón y esta será la ventana padre del JDialog que va a desplegar el botón.

El código para todo esto puede estar en el constructor de MiBoton y es algo como esto

this.addHierarchyListener(new HierarchyListener( )
{
public void hierarchyChanged( HierarchyEvent e )
{
// Se mira si el panel ya ha sido añadido a alguna ventana
Component ventana = SwingUtilities.getWindowAncestor( EditorListaStrings.this );

if( ventana != null )
{
// Se elimna la suscripción para evitar construir la
// ventana dos veces
EditorListaStrings.this.removeHierarchyListener( this );
// Construye el dialogo usando como padre ventana
construyeDialogo (ventana);
}
}

} );

No hay comentarios: