Introducción a Swing

Avanzado

Hoy en día, la mayoría de los programadores usan Swing o JavaFX para construir interfaces de usuario. Aquí, se introduce Swing. Swing es un framework que proporciona componentes GUI más potentes y flexibles que AWT. Como resultado, es la GUI la que ha sido ampliamente utilizada por los programadores de Java durante más de una década.

La sección de Swing se divide en tres partes. Esta parte presenta a Swing. Comienza describiendo los conceptos centrales de Swing. Luego presenta un ejemplo simple que muestra la forma general de un programa Swing. A continuación se muestra un ejemplo que utiliza la gestión de eventos. El artículo concluye explicando cómo se realiza la pintura en Swing.

1. El origen de Swing

Swing no existía en los primeros días de Java. Más bien, fue una respuesta a las deficiencias presentes en el subsistema GUI original de Java: el Abstract Window Toolkit. AWT define un conjunto básico de controles, ventanas y cuadros de diálogo que admiten una interfaz gráfica útil pero limitada. Una razón para la naturaleza limitada del AWT es que traduce sus diversos componentes visuales en sus correspondientes equivalentes específicos de plataforma o pares (peers). Esto significa que la apariencia de un componente está definida por la plataforma, no por Java. Debido a que los componentes AWT usan recursos de código nativo, se los denomina heavyweight.

El uso de peers nativos provocó varios problemas. En primer lugar, debido a las variaciones entre los sistemas operativos, un componente puede verse, o incluso actuar, de manera diferente en diferentes plataformas. Esta variabilidad potencial amenazaba la filosofía general de Java: escribir una vez, ejecutar en cualquier lugar. En segundo lugar, la apariencia de cada componente fue fija (porque está definida por la plataforma) y no se pudo (fácilmente) cambiar. En tercer lugar, el uso de componentes heavyweight causó algunas restricciones frustrantes. Por ejemplo, un componente heavyweight. siempre fue opaco.

No mucho después de la versión original de Java, se hizo evidente que las limitaciones y restricciones presentes en el AWT eran lo suficientemente serias como para necesitar un mejor enfoque. La solución fue Swing. Introducido en 1997, Swing se incluyó como parte de Java Foundation Classes (JFC). Swing estaba inicialmente disponible para su uso con Java 1.1 como una biblioteca separada. Sin embargo, a partir de Java 1.2, Swing (y el resto del JFC) se integró completamente en Java.

2. Componentes y contenedores

Una GUI Swing consta de dos elementos clave: componentes y contenedores. Sin embargo, esta distinción es principalmente conceptual porque todos los contenedores también son componentes. a diferencia entre los dos se encuentra en su propósito: un componente es un control visual independiente, como un botón o campo de texto. Un contenedor contiene un grupo de componentes.

Por lo tanto, un contenedor es un tipo especial de componente que está diseñado para contener otros componentes. Además, para que se muestre un componente, debe mantenerse dentro de un contenedor. Por lo tanto, todas las GUI de Swing tendrán al menos un contenedor. Como los contenedores son componentes, un contenedor también puede contener otros contenedores. Esto permite a Swing definir lo que se llama una jerarquía de contención, en la parte superior debe ser un contenedor de nivel superior.

2.1. Componentes

En general, los componentes Swing se derivan de la clase JComponent. (Las únicas excepciones a esto son los cuatro contenedores de nivel superior, que se describen en la siguiente sección). JComponent proporciona la funcionalidad que es común a todos los componentes. Por ejemplo, JComponent admite la look and feel conectables. JComponent hereda las clases AWT Container y Component. Por lo tanto, un componente Swing está integrado y es compatible con un componente AWT.

Todos los componentes de Swing están representados por clases definidas dentro del paquete javax.swing. La siguiente tabla muestra los nombres de clase para los componentes Swing (incluidos los utilizados como contenedores):

Tabla de Componentes y Contenedores Swing en Java
JApplet (obsoleto JDK 9)JButtonJCheckBoxJCheckBoxMenuItemJColorChooserJComboBox
JComponentJDesktopPaneJDialogJEditorPaneJFileChooserJFormattedTextField
JFrameJInternalFrameJLabelJLayerJLayeredPaneJList
JMenuJMenuBarJMenuItemJOptionPaneJPanelJPasswordField
JPopupMenuJProgressBarJRadioButtonJRadioButtonMenuItemJRootPaneJScrollBar
JScrollPaneJSeparatorJSliderJSpineerJSplitPaneJTabbedPane
JTableJTextAreaJTextFieldJTextPaneJTogglebuttonJToolBar
JToolTipJTreeJViewportJWindows

Observe que todas las clases de componentes comienzan con la letra J. Por ejemplo, la clase para una etiqueta es JLabel, la clase para un botón es JButton y la clase para para una casilla de verificación es JCheckBox

2.2. Contenedores

Swing define dos tipos de contenedores. Los primeros son contenedores de nivel superior: JFrame, JApplet, JWindow y JDialog. (JApplet, que admite applets basados ​​en Swing, ha sido descartado por JDK 9.) Estos contenedores no heredan JComponent. Sin embargo, heredan las clases AWT Component y Container. A diferencia de otros componentes de Swing, que son lightweight, los contenedores de nivel superior son heavyweight. Esto hace que los contenedores de nivel superior sean un caso especial en la biblioteca de componentes Swing.

Como su nombre lo indica, un contenedor de nivel superior debe estar en la parte superior de una jerarquía de contención. Un contenedor de nivel superior no está contenido en ningún otro contenedor. Además, cada jerarquía de contención debe comenzar con un contenedor de nivel superior. El más comúnmente utilizado para las aplicaciones es JFrame.

El segundo tipo de contenedor compatible con Swing es el contenedor lightweight. Los contenedores lightweight heredan JComponent. Ejemplos de contenedores lightweight son JPanel, JScrollPane y JRootPane. Los contenedores lightweight a menudo se usan para organizar y administrar colectivamente grupos de componentes relacionados porque un contenedor lightweight se puede contener dentro de otro contenedor. Por lo tanto, puede usar contenedores lightweight para crear subgrupos de controles relacionados que están contenidos dentro de un contenedor externo.

3. Paneles de Contenedor de Nivel Superior

Cada contenedor de nivel superior define un conjunto de paneles (panes). En la parte superior de la jerarquía hay una instancia de JRootPane. JRootPane es un contenedor lightweight cuyo objetivo es administrar los otros paneles. También ayuda a administrar la barra de menú opcional. Los paneles que componen el panel raíz (root pane) se denominan glass pane, content pane, y layered pane.

El glass pane es el panel de nivel superior. Se encuentra arriba y cubre por completo todos los demás paneles. El glass pane le permite administrar los eventos del mouse que afectan a todo el contenedor (en lugar de a un control individual) o, por ejemplo, pintar sobre cualquier otro componente. En la mayoría de los casos, no necesitará usar el glass pane directamente.

El layered pane permite que los componentes tengan un valor de profundidad. Este valor determina qué componente se superpone a otro. (Por lo tanto, el layered pane le permite especificar un orden Z para un componente, aunque esto no es algo que normalmente deba hacer). El layered pane contiene el content pane y la barra de menú (opcional).

4. Administrador de esquemas

Antes de comenzar a escribir un programa Swing, hay una cosa más que debe tener en cuenta: administrador de disposición/esquemas/diseño. El administrador de disposición controla la posición de los componentes dentro de un contenedor. Java ofrece varios administradores de disposición. La mayoría son provistas por AWT (dentro de java.awt), pero Swing agrega algunas propias. Todos los administradores de disposición son instancias de una clase que implementa la interfaz LayoutManager. (Algunos también implementarán la interfaz LayoutManager2.) Aquí hay una lista de algunos de los administradores de disposición disponibles para el programador Swing:

Tabla de Administrador de esquemas Swing Java.
Layout ManagersDefinición
FLowLayoutUn diseño simple que posiciona los componentes de izquierda a derecha, de arriba hacia abajo.
BorderLayoutPosiciones de componentes dentro del centro o los bordes del contenedor. Este es el diseño predeterminado para un content pone..
GridLayoutPresenta diferentes componentes de tamaño dentro de un grid flexible.
GridBagLayoutPresenta los componentes dentro de un grid.
BoxLayoutExpone componentes vertical u horizontalmente dentro de un box.
SpingLayoutPresenta componentes sujetos a una serie de restricciones.

5. Un programa simple Swing

Los programas Swing difieren de los programas basados en la consola que se muestran anteriormente en este curso. Los programas Swing no solo usan el componente Swing configurado para manejar la interacción del usuario, sino que también tienen requisitos especiales relacionados con hilos (threading). La mejor manera de entender la estructura de un programa Swing es trabajar a través de un ejemplo.

Aunque es bastante breve, el siguiente programa muestra una forma de escribir una aplicación Swing. En el proceso, muestra varias características clave de Swing. Utiliza dos componentes Swing: JFrame y JLabel. JFrame es el contenedor de nivel superior que se usa comúnmente para las aplicaciones Swing. JLabel es el componente de Swing que crea una etiqueta, que es un componente que muestra información. La etiqueta es el componente más simple de Swing porque es pasivo. Es decir, una etiqueta no responde a la entrada del usuario. Simplemente muestra la salida. El programa usa un contenedor JFrame para contener una instancia de JLabel. La etiqueta muestra un breve mensaje de texto.

// Un simple programa Swing

// Los programas Swing deben importar java.swing.
import javax.swing.*;

public class SwingDemo {

    SwingDemo(){

        // Crea un nuevo contenedor JFrame.
        JFrame jfrm=new JFrame("Una simple aplicación Swing");

        // Se le da al cuadro un tamaño inicial.
        jfrm.setSize(475,200);

        // Termine el programa cuando el usuario cierre la aplicación.
        jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // Crea una etiqueta basada en texto.
        JLabel jLabel= new JLabel("Programación GUI con Swing.");

        // Agregue la etiqueta al panel de contenido (content pane).
        jfrm.add(jLabel);

        // Visualiza el marco.
        jfrm.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run(){
                new SwingDemo();
            }
        });
    }
}

Los programas Swing se compilan y ejecutan de la misma manera que otras aplicaciones Java. Por lo tanto, para compilar este programa, puede usar esta línea de comando:

javac SwingDemo.java

Para ejecutar el programa, use esta línea de comando:

java SwingDemo

Cuando se ejecuta el programa, producirá la ventana que se muestra en la siguiente imagen:

Ejemplo simple de Swing Java
Ejemplo simple de Swing Java

6. Explicación de ejemplo Swing línea por línea

Debido a que el programa SwingDemo ilustra varios conceptos clave de Swing, lo examinaremos cuidadosamente, línea por línea. El programa comienza importando el siguiente paquete:

import javax.swing.*;

Este paquete javax.swing contiene los componentes y modelos definidos por Swing. Por ejemplo, define clases que implementan etiquetas, botones, controles de edición y menús. Este paquete se incluirá en todos los programas que usan Swing. A partir de JDK 9, javax.swing se encuentra en el módulo java.desktop.

6.1. Componentes de la aplicación

A continuación, el programa declara la clase SwingDemo y un constructor para esa clase. Comienza creando un JFrame, usando esta línea de código:

 JFrame jfrm=new JFrame("Una simple aplicación Swing");

Esto crea un contenedor llamado jfrm que define una ventana rectangular completa con una barra de título; cerrar, minimizar, maximizar y restaurar botones; y un menú del sistema. Por lo tanto, crea una ventana estándar de nivel superior. El título de la ventana se pasa al constructor.

Luego, la ventana se dimensiona usando esta declaración:

jfrm.setSize(475,200);

El método setSize() establece las dimensiones de la ventana, que se especifican en pixeles Su forma general se muestra aquí:

void setSize(int ancho, int alto);

En este ejemplo, el ancho de la ventana se establece en 475 y la altura se establece en 200.

De forma predeterminada, cuando se cierra una ventana de nivel superior (como cuando el usuario hace clic en el cuadro de cierre), la ventana se elimina de la pantalla, pero la aplicación no finaliza. Si bien este comportamiento predeterminado es útil en algunas situaciones, no es lo que se necesita para la mayoría de las aplicaciones. En su lugar, generalmente querrá que toda la aplicación finalice cuando se cierre su ventana de nivel superior. Hay un par de formas de lograr esto. La forma más fácil es llamar a setDefaultCloseOperation(), como lo hace el programa:

jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Después de que se ejecuta esta llamada, al cerrar la ventana, la aplicación completa finaliza. La forma general de setDefaultCloseOperation() se muestra aquí:

void setDefaultCloseOperation(int what)

El valor pasado en lo que determina qué sucede cuando la ventana está cerrada. Hay muchas otras opciones además de JFrame.EXIT_ON_CLOSE. Ellos se muestran aquí:

JFrame.DISPOSE_ON_CLOSE
JFrame.HIDE_ON_CLOSE
JFrame.DO_NOTHING_ON_CLOSE

Sus nombres reflejan sus acciones. Estas constantes se declaran en WindowConstants, que es una interfaz declarada en javax.swing implementada por JFrame.

6.2. Componentes de la aplicación (II)

La siguiente línea de código crea un componente JLabel:

 JLabel jLabel= new JLabel("Programación GUI con Swing.");

JLabel es el componente Swing más fácil de usar porque no acepta la entrada del usuario. La etiqueta creada por el programa contiene solo texto, que se pasa a su constructor.

La siguiente línea de código agrega la etiqueta al panel de contenido del frame:

jfrm.add(jLabel);

Como se explicó anteriormente, todos los contenedores de nivel superior tienen un panel de contenido (content pane) en el que se almacenan los componentes. Por lo tanto, para agregar un componente a un frame, debe agregarlo al panel de contenido del frame. Esto se logra llamando a add() en la referencia de JFrame (jfrm en este caso). El método add() tiene varias versiones. La forma general de la utilizada por el programa se muestra aquí:

Component add(Component comp)

De forma predeterminada, el panel de contenido asociado con un JFrame utiliza un diseño de borde. Esta versión de add() agrega el componente (en este caso, una etiqueta) a la ubicación central. Otras versiones de add() le permiten especificar una de las regiones fronterizas. Cuando se agrega un componente al centro, su tamaño se ajusta automáticamente al tamaño del centro.

La última instrucción en el constructor SwingDemo hace que la ventana se vuelva visible.

jfrm.setVisible(true);

El método setVisible() tiene esta forma general:

void setVisible(boolean indicador)

Si el indicador es true, se mostrará la ventana. De lo contrario, estará oculto. Por defecto, un JFrame es invisible, por lo que debe llamarse a setVisible(true) para mostrarlo.

6.3. Componentes de la aplicación (III)

Dentro de main(), se crea un objeto SwingDemo, que hace que se muestren la ventana y la etiqueta. Observe que el constructor SwingDemo se invoca utilizando estas líneas de código:

SwingUtilities.invokeLater(new Runnable() {
public void run(){
new SwingDemo();
}
});

Esta secuencia hace que se cree un objeto SwingDemo en el hilo de despacho de eventos en lugar de en el hilo principal de la aplicación. Este es el por qué. En general, los programas Swing son impulsados ​​por eventos. Por ejemplo, cuando un usuario interactúa con un componente, se genera un evento. Se pasa un evento a la aplicación llamando a un controlador de eventos definido por la aplicación. Sin embargo, el controlador se ejecuta en el hilo de despacho de eventos provisto por Swing y no en el hilo principal de la aplicación. Por lo tanto, aunque los controladores de eventos están definidos por su programa, se invocan a un hilo que no fue creado por su programa.

Para evitar problemas (como dos subprocesos diferentes que intentan actualizar el mismo componente al mismo tiempo), todos los componentes de Swing GUI se deben crear y actualizar desde el subproceso de despacho de eventos, no desde el subproceso principal de la aplicación. Sin embargo, main() se ejecuta en el hilo principal. Por lo tanto, no puede instanciar directamente un objeto SwingDemo. En su lugar, debe crear un objeto Runnable que se ejecute en el subproceso de despacho de eventos y hacer que este objeto cree la GUI.

6.4. Componentes de la aplicación (IIV)

Para permitir que se cree el código GUI en el hilo de despacho de eventos, debe usar uno de los dos métodos definidos por la clase SwingUtilities. Estos métodos son invokeLater() e invokeAndWait(). Ellos se muestran aquí:

static void invokeLater(Runnable obj)
static void invokeAndWait(Runnable obj)
throws InterruptedException, InvocationTargetException

Aquí, obj es un objeto Runnable que tendrá su método run() llamado por el hilo de despacho de eventos. La diferencia entre los dos métodos es que invokeLate() devuelve inmediatamente, pero invokeAndWait() espera hasta que el obj.run() devuelva. Puede utilizar estos métodos para llamar a un método que construya la GUI para su aplicación Swing, o cuando necesite modificar el estado de la GUI a partir de código no ejecutado por el hilo de despacho de eventos.

Un punto más: el programa anterior no responde a ningún evento, porque JLabel es un componente pasivo. En otras palabras, un JLabel no genera ningún evento. Por lo tanto, el programa anterior no incluye ningún controlador de eventos. Sin embargo, todos los demás componentes generan eventos a los que su programa debe responder, como lo muestran los próximos ejemplos.

Java Swing
  • Introducción a Swing
Sending
User Review
5 (2 votes)

Sobre el Autor:

Hey hola! Yo soy Alex Walton y tengo el placer de compartir conocimientos hacía ti sobre el tema de Programación en Java, desde cero, Online y Gratis.

Deja una Respuesta

*

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.