## Cómo usar la clase JLayeredPane

Un LayeredPane es un componente Swing que proporciona una tercera dimensión para posicionar componentes: profundidad, también conocida como eje Z. Cuando se añade un componente a un panel por capas, se especifica su profundidad. Los frames con mayor profundidad siempre solapan los frames con menor profundidad y los frames con menor profundidad siempre están debajo de frames con mayor profundidad. Los frames con la misma profundidad pueden cambiar su posición. Por conveniencia, LayeredPane define varias layers (capas) dentro del rango posible de profundiades para funciones específicas. Por ejemplo, podemos poner un componente en la capa de mayor funcionalidad, la capa de arrastre, cuando se arrastan componentes.

Todo contenedor Swing que tiene un panel raíz -- como JFrame, JApplet, JDialog, y JInternalFrame -- automáticamente tiene un layeredpane, aunque la mayoría de los programas no los utilizan explícitamente. Podemos crear nuestro propio layeredpane y utilizarlo en cualquier lugar como un contenedor normal Swing.

Swing proporciona dos clases de paneles por capas. La primera, JLayeredPane, es la clase que utilizan los paneles raíz. La segunda, JDesktopPane, es una subclase de JLayeredPane que está especializada para contener frames internos. El ejemplo de esta sección utiliza un ejemplar de JLayeredPane. Para ver ejemplos de utilización de JDesktopPane puedes ir a Cómo usar Frames Internos.

Aquí podemos ver una imagen de una aplicación que utiliza paneles de capas para manejar JInternalFrames en diferentes capas:

> Intenta esto:
> 1. Compila y ejecuta la aplicación. El fichero fuente es LayeredPaneDemo.java. También necesitarás cinco ficheros de imágenes: Bird.gif, Cat.gif, Dog.gif, Rabbit.gif, y Pig.gif.
> 2. Cuando arranca, el programa crea cinco frames internos. Para crear otro frame, selecciona una capa desde el combo box luego pulsa el botón Create a Frame.
> 3. Mueve los frames alrededor. Observa la relación de los frames en las diferentes capas y los frames de al misma capa.
> 4. Observa que se puede arrastrar un frame interno sobre los controles de la parte superior del programa. Los controles están en el panel de contenido del frame principal que está en una capa inferior a todas las capas disponibles desde el menú.

Las clases JFrame, JApplet, JDialog, y JInternalFrame proporcionan un método de conveniencia, getLayeredPane, para obtener el panel raíz del layeredpane.LayeredPaneDemo.java utiliza este método para obtener el layeredpane al que añadirle los frames internos:

    public class LayeredPaneDemo extends JFrame ... {
        ...
        public LayeredPaneDemo() {
            ...
            layeredPane = getLayeredPane();
        ...

Aquí puedes ver el código que crea y añade frames internos al layeredpane:

    private void addNewInternalFrame(int index) {
        JInternalFrame newFrame = new JInternalFrame();
        ...
        numFrames++;
        newFrame.setBounds(30*(numFrames%10), 30*(numFrames%10)+55, 200, 160);
        ...
        Integer layer = layerValues[index];
        layeredPane.add(newFrame, layer);
        try { newFrame.setSelected(true); } catch (java.beans.PropertyVetoException e2) {}
    }

Las líneas en negrita muestran dónde se añade al frame al layeredpane. El método add utilizado en este programa toma dos argumentos. El primero es el componente a añadir; el segundo es un Integer indicando la profundidad donde poner el componente. El valor puede ser cualquier Integer. Sin embargo, la mayoría de los programas utilizarán uno de aquellos definidos por la clase JLayeredPane:

| Nombre de Capa | Valor | Descripción
--- | --- | --- | ---
FRAME_CONTENT_LAYER | new Integer(-30000) | Esta capa es utiliza pra posicionar el panel de contenido del frame y la barra de menú. La mayoría de los programas no la utilizarán.
DEFAULT_LAYER | new Integer(0) | La mayoría de los componentes van en esta capa.
PALETTE_LAYER | new Integer(100) | Esta capa es útil para paletas y barras de herramientas flotantes.
MODAL_LAYER | new Integer(200) | Los diálogos modales, como aquellos proporcionados por JOptionPane, pertenecen a esta capa.
POPUP_LAYER | new Integer(300) | Los desplegables van en esta capa porque necesitan aparecer por encima de todo.
DRAG_LAYER | new Integer(400) | Un componente se mueve a esta capa cuando se arrasta. Se debe devolver el componente a su capa normal cuando se suelta.

La posición de un componente determina su relación con otros componentes de la misma capa. Al contrario que los números de capas, cuando más bajo sea el número de posición más alto estará el componente en su capa.

Se puede seleccionar la posición de un componente cuando se le añade al layeredpane proporcionando un tercer argumento al método add. Las posiciones se especifican con un int entre -1 y (N-1), donde N es el número de componentes en la capa. Utilizar -1 es lo mismo que utilizar N-1; indica la posición más inferior. Utilizar 0 especifica que el componente debería ir en la posición superior de su capa. Como se ve en la siguiente figura, con la excepción de -1, un número de posición menor indica una posición superior dentro de la capa.

Tanto la capa de un componente como su posición relativa dentro de la capa pueden cambiar. Para cambiar la capa de un componente normalmente se utiliza el método setLayer. Para cambiar la posición de un componente dentro de su capa, se puede utilizar los métodos moveToBack y moveToFront proporcionados por JLayeredPane.

> Una Nota de Precaución: Cuando se añade un componente a una LayeredPane se especifica la capa con un Integer. Cuando se utiliza setLayer para cambiar al capa de un componente, se utiliza un int. Mira las tablas que hay abajo para comprobar los tipos de los argumentos y de los valores de retorno para otros métodos de esta clase que trabajan con capas.

#### El API LayeredPane

> Las siguientes tablas listan los métodos y constructores más utilizados de la clase JLayeredPane. Otros métodos interesantes están definidos por las clases JComponent y Component.

> El API para utilizar LayeredPane se divide en estas categorías:

> - Crear u Obtener un LayeredPane
> - Situar Componentes en capas
> - Posicionar Componentes dentro de una Capa

> Crear u Obtener un LayeredPane
> Método | Propósito
> --- | ---
> JLayeredPane() | Crea un LayeredPane.
> JLayeredPane getLayeredPane() (en JApplet, JDialog, JFrame, y JInternalFrame) | Obtiene el LayeredPAne en un applet, dialog, frame, o frame interno.

> Situar Componentes en Capas
> Método | Propósito
> --- | ---
> void add(Component, Integer) void add(Component, Integer, int) | Añade el componente especificado al layeredpane. El segundo argumento indica la capa. El tercer argumento, cuando existe, indica la posición del componente dentro de la capa.
> void setLayer(Component, int) void setLayer(Component, int, int)< | Cambia la capa del componente. El segundo argumento indica la capa, el tercer argumento, cuando existe, indica la posición del componente dentro de la capa.
> int getLayer(Component) int getLayer(JComponent) | Obtiene la capa del componente especificado.
> int getComponentCountInLayer(int) | Obtiene el número de componentes en la capa especificada. El valor devuelto por este método puede ser útil para calcular los valores de posición.
> Component[] getComponentsInLayer(int) | Obtiene un array con todos los componentes en el capa especificada.
> int highestLayer() int lowestLayer() | Calcula la capa más alta o más baja actualmente utilizadas.

> Posicionar Componentes en una Capa
> Método | Propósito
> --- | ---
> void setPosition(Component, int) int getPosition(Component) | Selecciona u obtiene la posición del componente especificado dentro de su capa.
> void moveToFront(Component) void moveToBack(Component) | Mueve el componente especificado adelante o atrás en su capa.

#### Ejemplos que utilizan LayeredPane

> Esta tabla muestra ejemplos que utilizan JLayeredPane y dónde poder encontarlos.

> Ejemplo | Dónde se Describe | Notas
> --- | --- | ---
> LayeredPaneDemo.java | Esta Página. | Ilustra las capas y las posiciones inter-capas de un JLayeredPane.
> InternalFrameDemo.java | Cómo usar Frames Internos | Utiliza un JDesktopFrame para manejar frames internos.

Ozito