Cómo utilizar la clase RootPane

En general, no se crea directamente un objeto JRootPane. En su lugar, se obtiene un JRootPane (tanto si se quiere como si no!) cuando se ejemplariza un JInternalFrame o uno de los contenedores Swing de alto nivel -- JApplet, JDialog, JFrame, y JWindow.

La página Reglas Generales para Usar Componentes Swing explica lo básico sobre el uso de paneles raíz -- obtener el panel de contenido, seleccionar su controlador de distribución, y añadirle componentes Swing. Esta página explica más cosas sobe los paneles raíz, incluyendo los componentes que crean un panel raíz, y cómo poder utilizarlos.

Un panel raíz se divide en cuatro partes:

El Panel de Cristal
Oculto, por defecto. Si se hace visible, es como si se pusiera una hoja de cristal sobre las otras partes del panel raiz. Es completamente transparente (a menos que hagamos que el método paint haga algo) e intercepta los eventos de entrada para el panel raíz. En la siguiente sección, veremos un ejemplo de utilización de un panel de cristal.
El panel de capas
Sirve para posicionar sus contenidos, que consisten en el panel de contenido y la barra de menú opcional. También puede contener otros componentes en un orden Z especificado. Para más información puedes ver Cómo usar Layered Panes.
El Panel de Contenido
El contenedor de los componentes visibles del panel raíz, excluyendo la barra de menú.
La barra de menú opcional
El hogar para los menús del panel de contenido. Si el contenedor tiene una barra de menús, generalmente se utilizan los métodos setMenuBar o setJMenuBar del contenedor para poner la barra de menú en el lugar apropiado.

El Panel de Cristal

El panel de cristal es útil cuando queremos poder capturar eventos o dibujar sobre un área que ya contiene uno o más componentes. Por ejemplo, podemos desactivar los eventos de ratón para una región multi-componente haciendo que el panel de cristal intercepte los eventos. O podemos mostrar un cursor de espera sobte en panel raíz completo utilizando el panel de cristal.

Aquí podemos ver una imagen de una aplicación que demuestra las características del panel de cristal. Contiene un checkbox que permite seleccionar si el panel de cristal es "visible" -- se puede obtener eventos y dibujar sobre su propia parte de pantalla. Cuando un panel de cristal es visible, bloquea todas las entradas desde los componentes del panel de contenidos. También dibuja un punto rojo donde se detectó el último evento de pulsación de ratón.


Intenta esto:
  1. Compila y ejecuta la aplicación. El fichero fuente es GlassPaneDemo.java.
  2. Pulsa le botón 1.
    La apariencia del botón cambia para indicar que ha sido pulsado.
  3. Pulsa el checkbox para que el panel de cristal se vuelva "visible", y luego pulsa el botón 1, otra vez.
    El botón no detecta la pulsación del ratón porque el panel de cristal la ha interceptado. Cuando el panel de cristal detecta el evento, suena un pitido y dibuja un círculo rojo donde se pulsó.
  4. Pulsa de nuevo sobre el checkbox para ocultar el panel de cristal.
    Cuando el panel raíz detecta un evento sobre el checkbox, lo reenvía al checkbox. De otro modo, el checkbox no podría responder a las puslaciones.

El siguiente código de GlassPaneDemo.java muestra y oculta el panel de cristal. Sucede que este programa para crear su propio panel de cristal lo selecciona utilizando el método setGlassPane de JFrame. Sin embargo, si un panel de cristal no hace ningún dibujo, el programa podría simplemente añadir oyentes al panel de cristal por defecto, como los devueltos por getGlassPane.
...//where GlassPaneDemo's UI is initialized:
JCheckBox changeButton =
        new JCheckBox("Glass pane \"visible\"");
changeButton.setSelected(false);
changeButton.addItemListener(new ItemListener() {
    public void itemStateChanged(ItemEvent e) {
        myGlassPane.setVisible(e.getStateChange()
                               == ItemEvent.SELECTED);
    }
});
El siguiente fragmento de código implementa el manejo de eventos de raton para el panel de cristal. Si ocurre un evento de ratón sobre el checkbox o la barra de menús, entonces el panel de cristal redirecciona el evento para que el checkbox o el menú lo reciban. Para que el checkbox y el menú se comporten apropiadamente, también reciben todos los eventos drag que empiezan con una pulsación en el checkbox o en la barra de menú.
...//In the implementation of the glass pane's mouse listener:
public void mouseMoved(MouseEvent e) {
    redispatchMouseEvent(e, false);
}

.../* The mouseDragged, mouseClicked, mouseEntered,
    * mouseExited, and mousePressed methods have the same
    * implementation as mouseMoved*/...

public void mouseReleased(MouseEvent e) {
    redispatchMouseEvent(e, true);
    inDrag = false;
}

private void redispatchMouseEvent(MouseEvent e, boolean repaint) {
    boolean inButton = false;
    boolean inMenuBar = false;
    Point glassPanePoint = e.getPoint();
    Component component = null;
    Container container = contentPane;
    Point containerPoint = SwingUtilities.convertPoint(
                                    glassPane,
                                    glassPanePoint,
                                    contentPane);
    int eventID = e.getID();

    if (containerPoint.y < 0) {
        inMenuBar = true;
        //...set container and containerPoint accordingly...
        testForDrag(eventID);
    }

    component = SwingUtilities.getDeepestComponentAt(
                                    container,
                                    containerPoint.x,
                                    containerPoint.y);

    if (component.equals(liveButton)) {
        inButton = true;
        testForDrag(eventID);
    }

    if (inMenuBar || inButton || inDrag) {
        ...//Redispatch the event to component...
    }

    if (repaint) {
        toolkit.beep();
        glassPane.setPoint(glassPanePoint);
        glassPane.repaint();
    }
}

private void testForDrag(int eventID) {
    if (eventID == MouseEvent.MOUSE_PRESSED) {
        inDrag = true;
    }
}
Aquí está el código que implementa el dibujo para el panel de cristal:
...//where GlassPaneDemo's UI is initialized:
myGlassPane = new MyGlassPane(...);
frame.setGlassPane(myGlassPane);
...
/**
 * We have to provide our own glass pane so that it can paint.
 */
class MyGlassPane extends JComponent {
    Point point = null;

    public void paint(Graphics g) {
    	if (point != null) {
	    g.setColor(Color.red);
    	    g.fillOval(point.x - 10, point.y - 10, 20, 20);
    	}
    }
    ...
}

El API de Root Pane

Las siguientes tablas listan el API para utilizar paneles raíz, paneles de cristal y paneles de contenido:

El API para utilizar otras partes del panel raíz se describe en :

Usar un Panel Raíz
Método Propósito
JRootPane getRootPane()
(en JApplet, JDialog, JFrame, JInternalFrame, y JWindow)
Obtiene el panel raíz del applet, dialog, frame, internal frame, o window.
JRootPane SwingUtilities.getRootPane(Component) Si el componente tiene un panel raíz, lo devuelve. Si no es así, devuelve el panel raíz (si existe) que contiene el componente.
JRootPane getRootPane()
(en JComponent)
Invoca al método SwingUtilitiesgetRootPane sobre JComponent.
void setDefaultButton(JButton)
JButton getDefaultButton()
Selecciona u obtiene qué botón (si existe) es el botón por defecto del panel raíz. Una acción específica del aspecto y comportamiento, como pulsar ENTER, hace que se realice la acción del botón.

Seleccionar u Obtener el Panel de Cristal
Método Propósito
setGlassPane(Component)
Component getGlassPane()

(en JApplet, JDialog, JFrame, JInternalFrame, JRootPane, y JWindow)
Selecciona u obtiene elpanel de cristal.

Usar el Panel de Contenido
Método Propósito
setContentPane(Container)
Container getContentPane()

(en JApplet, JDialog, JFrame, JInternalFrame, JRootPane, y JWindow)
Selecciona u obtiene el panel de contenido.

Ejemplos que utilizan Paneles Raíz

Todo programa Swing utiliza un panel raíz. Los ejemplos de esta lista ilustran algunos de los usos más comunes e interesantes. También puedes ver:

Ejemplo Dónde se describe Notas
GlassPaneDemo.java Esta página Usa una panel de cristal y redirecciona los eventos.


Ozito