## Cómo Crear Frames (Ventanas Principales)

La mayoría de las aplicaciones Swing presentan su GUI principal dentro de un JFrame -- un contenedor Swing de alto nivel que proporciona ventanas para applets y aplicaciones. Un frame tiene decoraciones como un borde, un título, y botones para cerrar y minimizar la ventana. Un programa típico símplemente crea un frame, añade componentes al panel de contenido, y quizás añade una barra de menú. Sin embargo, a través de su panel raíz, JFrame proporciona soporte para una mayor personalización.

Para crear una ventana que sea dependiente de otra ventana -- que desaparezca cuando la otra ventana se minimiza, por ejemplo -- se utiliza un diálogo en vez de un frame. Para crear una ventana que aparece dentro de otra ventana se utiliza un frame interno.

Aquí podemos ver dos imágenes del mismo programa, FrameDemo.java, ejecutándose en distintas plataformas. El programa trae un frame que contiene algo interesante que ver.

Solaris | Windows
--- | ---
| [PENDIENTE]

> Nota:La decoración de un frame es dependiente del sistema. No se puede cambiar la decoración de un frame.

Abajo podemos ver el código de FrameDemo.java que crea el frame del ejemplo anterior.

    public static void main(String s[]) {
        JFrame frame = new JFrame("A Basic Frame");

        WindowListener l = new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
    	    System.exit(0);
            }
        };
        frame.addWindowListener(l);

        JLabel aLabel = new JLabel("Something to look at",
                                           new ImageIcon("images/beach.gif"),
                                           JLabel.CENTER);
        aLabel.setVerticalTextPosition(JLabel.TOP);
        aLabel.setHorizontalTextPosition(JLabel.CENTER);
        frame.getContentPane().add(aLabel, BorderLayout.CENTER);

        frame.pack();
        frame.setVisible(true);
    }

El código crea un frame con el título A Basic Frame y añade un oyente de window para salir del programa cuando el usuario cierre el frame.

Las líneas en itálica del código crean la etiqueta que muestra el texto y la imagen del frame. Este es esencialmente el GUI del programa. Si queremos utilizar este programa como marco de trabajo para nuestros propios programas, sólo tenemos que reemplazar el código en itálica para crear los componentes que querramos.

El código en negrita añade la etiqueta al panel de contenido del frame. Puedes ir a Añadir Componentes a un Frame para más detalles y ejemplos.

Para que un frame aparezca en la pantalla, un programa debe llamar a setSize o a pack, y luego llamar a setVisible(true) o su equivalente, show. Este programa empaqueta el frame y utiliza setVisible. Observa que si cualquier parte del GUI ya es visible, deberíamos invocar a setVisible desde el thread de lanzado de eventos. Puedes ver la página Threads y Swing.

Este código es típico de muchos programas y es el marco de trabajo que hemos utilizado para crear la mayoría de los ejemplos de esta lección (incluyendo GlassPaneDemo.java y BorderDemo.java). Algunos ejemplos como TextFieldDemo.java y TableDemo.java, subclasifican JFrame y ejemplarizan la subclase frame en vez JFrame. En esos programas, el GUI se crea en el constructor de la subclase. Podríamos hacer esto en nuestros programas si necesitaramos subclasificar JFrame por alguna razón.

JFrame es una subclase de java.awt.Frame a la que añade soporte para la interposición de entradas y comportamiento de pintado contra el frame hijo, situando hijos en diferentes "capas" (layers) y para barras de menús Swing. Generalmente hablando, deberíamos utilizar JFrame en vez de Frame, por estas razones:

- Para aprovechar las nuevas características proporcionadas por su panel raíz como el panel transparente y el panel de capas.
- JFrame permite personalizar el comportamiento de la ventana, llamando al método setDefaultCloseOperation en vez de escribir un oyente de window.
- JFrame soporta el método revalidate.
- Los menús Swing funcionan mejor en un JFrame debido a sus métodos setJMenuBar.
- Deberíamos utilizar JFrame en un applet si éste utiliza componentes Swing. También, recomendamos la utilización de JFrame en una aplicación que utilice componentes Swing, aunque no es necesario.

#### Añadir Componentes a un Frame

> Como se ha visto en FrameDemo.java, para añadir componentes a un JFrame, se añaden a su panel de contenido. Las dos técnicas más comunes para añadir componetes al panel de contenido de un frame son:
> - Crear un contenedor como un JPanel, JScrollPane, o un JTabbedPane, y añadirle componentes, luego utilizar JFrame.setContentPane para convertirlo en el panel de contenido del frame.

>   TableDemo.java utiliza esta técnica. El código crea un panel desplazable para utilizarlo como panel de contenido del frame. Hay una tabla en el panel desplazable:

>       public class TableDemo extends JFrame {

>           public TableDemo() {
>               super("TableDemo");

>               MyTableModel myModel = new MyTableModel();
>               JTable table = new JTable(myModel);
>               table.setPreferredScrollableViewportSize(new Dimension(500, 70));

>               //Create the scroll pane and add the table to it.
>               JScrollPane scrollPane = new JScrollPane(table);

>               //Add the scroll pane to this window.
>               setContentPane(scrollPane);

>       	. . .

> - Utilizar JFrame.getContentPane para obtener el panel de contenido del frame. Añadir componentes al objeto devuelto.LayeredPaneDemo.java utiliza esta técnica mostrada aquí:

>       ...//create the components...
>       //get the content pane, add components to it:
>       Container contentPane = getContentPane();
>       // use a layout manager that respects preferred sizes
>       contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
>       contentPane.add(Box.createRigidArea(new Dimension(0, 10)));
>       contentPane.add(controls);
>       contentPane.add(Box.createRigidArea(new Dimension(0, 10)));
>       contentPane.add(emptyArea);

>   El controlador de disposición por defecto para el panel de contenido de un frame es BorderLayout. Cómo se ha visto en los ejemplos anteriores, se puede invocar al método setLayout sobre el panel de contenidos para cambiar su controlador de disposición.

#### EL API JFrame

> Las siguientes tablas listan los métodos y constuctores más utilizados de JFrame. Existen otros métodos que podríamos llamar y que están definidos en las clases Frame y Window y que incluyen pack, setSize, show, hide, setVisible, setTitle, y getTitle.

> La mayor parte de la opración de un frame está manejada por otros objetos. Por ejemplo, el interior de un frame está manejado por su panel raíz, y el panel de contenido contiene el GUI del frame.

> El API para utilizar Frames se divide en dos categorías:

> - Crear y Configurar un Frame
> - Seleccionar y Obtener los objetos auxiliares de un Frame

> Crear y Configurar un Frame
> Método | Propósito
> --- | ---
> JFrame() JFrame(String) | Crea un frame. El argumento String proporciona el título del frame.
> void setDefaultCloseOperation(int) int getDefaultCloseOperation() | Selecciona u obtiene la operación que ocurre cuando el usuario pulsa el botón de cerrar la ventana. Las posibles elecciones son: DO_NOTHING_ON_CLOSE HIDE_ON_CLOSE (por defecto) DISPOSE_ON_CLOSE Estas constantes están definidas en el interface WindowConstants.

> Seleccionar y Obtener los objetos auxiliares de un Frame
> Método | Propósito
> --- | ---
> void setContentPane(Container) Container getContentPane() | Selecciona u obtiene el panel de contenido del frame. También se puede hacer a través del panel raíz del frame.
> JRootPane createRootPane() void setRootPane(JRootPane) JRootPane getRootPane() | Crea, selecciona u obtiene el panel raíz del frame. El panel raíz maneja el interior de frame, incluyendo el panel de contendido, el panel transparente, etc.
> void setJMenuBar(JMenuBar) JMenuBar getJMenuBar() | Selecciona u obtiene la barra de menú del frame. También se puede hacer a través del panel raíz del frame.
> void setGlassPane(Component) Component getGlassPane() | Selecciona u obtiene el panel transparente del frame. También se puede hacer a través del panel raíz del frame.
> void setLayeredPane(JLayeredPane) JLayeredPane getLayeredPane() | Selecciona u obtiene el panel de capas del frame. También se puede hacer a través del panel raíz del frame.

#### Ejemplos que utilizan Frames

> Esta tabla lista ejemplos que utilizan JFrame y dónde poder encontrarlos.

> Ejemplo | Dónde se describe | Notas
> --- | --- | ---
> FrameDemo.java | Esta página. | Un frame básico con un componente.
> TextFieldDemo.java | Cómo usar TextFields | Una subclase de JFrame.
> TableDemo.java | Cómo usar Tablas | Una subclase de JFrame que configura el panel de contenido del frame.
> IconDemoApplet.java | Como usar Iconos | Añade muchos componentes al panel de contenido por defecto.
> LayeredPaneDemo.java | Cómo usar LayeredPane | Ilustra el uso de panel de capas del frame.
> GlassPaneDemo.java | El panel Transparente | Ilustra el uso del panel transparente.
> MenuDemo.java | Cóm usar Menús | Muestra como poner un JMenuBar en un JFrame.

Ozito