La aplicación SwingAplication presentada en la sección anterior es muy sencilla. Trae una ventana que se parece a ésta:
Cada vez que el usuario pulsa el botón, la etiqueta se actualiza. Puedes encontrar el programa completo en SwingApplication.java.
Esta página explica el programa en detalle, incluyendo los siguientes aspectos:
La siguiente línea importa el paquete principal de Swing:import javax.swing.*;
Nota: Las primeras versiones beta del JFC/Swing y del JDK 1.2 usaban nombres de paquetes diferentes. Puedes ver Nombres de Paquetes Swing para más detalles.
Los programas Swing también necesitan clases de los paquetes principales del AWT:
import java.awt.*; import java.awt.event.*;
Aquí puedes ver el código que utiliza SwingApplication para seleccionar su aspecto y comportamiento:public static void main(String [] args) { try { UIManager.setLookAndFeel( UIManager.getCrossPlatformLookAndFeelClassName()); } catch (Exception e) { } ..//Crea y muestra el GUI... }
El código anterior, esencialmente dice, "No me importa si el usuario a elegido un aspecto y comportamiento -- utiliza el aspecto y comportamiento multi-plataforma." Esta aproximación dictatorial tiene sentido cuando el program ha sido diseñado con un aspecto y comportamiento particular en mente. El aspecto y comportamiento multi-plataforma es conocido como Aspecto y Comportamiento Java (con el nick "Metal").
Para más información sobre cómo especificar el aspecto y comportamiento, puedes ver la página Cómo Seleccionar el Aspecto y Comportamiento
Todo programa que presente un GUI Swing contiene al menos un contenedor Swing de alto nivel. Para la mayoría de los programas, los contenedores de alto nivel Swing son ejemplares de JFrame, JDialog, o (para los applets) JApplet. Cada objeto JFrame implementa una ventana secundaria. Cada objeto JApplet implementa un área de pantalla de un applet dentro de una ventana del navegador. Un contenedor de Alto Nivel Swing porporciona el soporte que necesitan los componentes Swing para realizar su dibujado y su manejo de eventos.El ejemplo SwingApplication tiene un sólo contenedor de alto nivel, un JFrame. Cuando el usuario cierra el frame, la aplicación finaliza. Aquí está el código que configura y muestra el frame:
public class SwingApplication { ... public static void main(String[] args) { ... JFrame frame = new JFrame("SwingApplication"); //...create the components to go into the frame... //...stick them in a container named contents... frame.getContentPane().add(contents, BorderLayout.CENTER); //Finish setting up the frame, and show it. frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); frame.pack(); frame.setVisible(true); } }
Para más información sobre los contenedores de alto nivel puedes ver Los Componentes Swing y el Árbol de Herencia de Contenedores
Como la mayoría de los GUIs, el ejemplo de SwingApplication contiene un botón y una etiqueta. (Al contrario que la mayoría de los GUIs, esto es todo lo que tiene SwingApplication). Aquí podemos ver el código que inicializa el botón:JButton button = new JButton("I'm a Swing button!"); button.setMnemonic('i'); button.addActionListener(this);
La primera línea crea el botón, La segunda línea selecciona la letra "i" como mnemónico que el usuario puede utilizar para simular un click del botón. Por ejemplo, en el Aspecto y Comportamiento Metal, teclear Alt+i resulta en un click del botón. La tercera línea registra un manejador de eventos para el click del botón. Podremos ver el código del manejador de eventos en Menajear Eventos.
Aquí podemos ver el código que inicializa y manipula la etiqueta:
...//where instance variables are declared: private static String labelPrefix = "Number of button clicks: "; private int numClicks = 0; ...//in GUI initialization code: final JLabel label = new JLabel(labelPrefix + "0 "); ... label.setLabelFor(button); ...//in the event handler for button clicks: label.setText(labelPrefix + numClicks);
El código anterior es bastante conocido, excepto la línea que invoca al método setLabelFor. Este código existe sólo para indicar a las tecnologías asistivas que la etiqueta describe el botón. Para más información, puedes ver Supporting Assistive Technologies.
Finalmente, aquí está el código que inicializa el panel:
JPanel pane = new JPanel(); pane.setBorder(BorderFactory.createEmptyBorder(30, 30, 10, 30)); pane.setLayout(new GridLayout(0, 1)); pane.add(button); pane.add(label);
Para más información sobre los componentes Swing como los botones y las etiquetas, puedes ver Usar Componentes Swing
SwingApplication agrupa la etiqueta y el botón en un contenedor (un JPanel) antes de añadir los componentes al frame. Aquí está el código que inicializa el panel:JPanel pane = new JPanel(); pane.setBorder(BorderFactory.createEmptyBorder(30, 30, 10, 30)); pane.setLayout(new GridLayout(0, 1)); pane.add(button); pane.add(label);
La primera línea de código crea el panel. La segunda le añade un borde; explicaremos los bordes más tarde.
La tercera línea de código crea un controlador de distribución que fuerza el contenido del panel a dibujarse en una sóla columna. La última línea añade el botón y la etiqueta al panel. Añadir el botón y la etiqueta al panel significa que están controlados por el controlador de distribución del panel. Específicamente, el controlador de distribución de un contenedor determina el tamaño y la posición de cada componente que haya sido añadido al contenedor.
Los conceptos de los controladores de distribución se describen en Controladores de Distribución. Para aprender cómo usar controladores de distribución individuales, puedes ver la lección Distribuir Componentes Dentro de un Contenedor.
Aquí está, de nuevo, el código que añade el borde al JPanel:pane.setBorder(BorderFactory.createEmptyBorder( 30, //top 30, //left 10, //bottom 30) //LEFT );
Este borde simplemente proporciona un espacio en blanco alrededor del panel de contenidos -- 30 pixels extras en la parte superior, izquierda y derecha y 10 pixels extras en la parte inferior. Los bordes son una caracterísitcas que JPanel de la clase Component.
Los conceptos de los bordes se describen en Control de la distribución y en Dibujo
El ejemplo SwingApplication contiene dos manejadores de eventos. Uno maneja las pulsaciones del botón (eventos action) y otro maneja los eventos de cerrar ventana:button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { numClicks++; label.setText(labelPrefix + numClicks); } }); ... frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } });
Puedes leer sobre el manejo de eventos Swing en Manejo de Eventos y en la lección Escribir Oyentes de Eventos.
El programa SwingApplication es de thread seguro. Una vez que su GUI es visible, en el manejador de eventos sólo ocurre manipulación GUI (actualizar la etiqueta). Como el manejador de eventos se ejecuta en el mismo thread que realiza todo el manejo de eventos y pintado de la aplicación, no existe la posibilidad de que dos threads intenten manipular el GUI a la vez.Sin embargo, es fácil introducir problemas de threads en un programa.
Puedes ver Threads y Swing para más información sobre los threads seguros en Swing.
El soporte para tecnologías asistivas -- dispositivos como lectores de pantalla que proporcionan formas alternativas de acceder a la información de un GUI -- ya está incluido en cada componente Swing. El único código que existen en SwingApplication que maneja el soporte de tecnologías asistivas es este:label.setLabelFor(button);
Además, la siguientes líneas seleccionan la información que puede ser utilizada por tecnologías asistivas:
super("HelloSwing"); JButton button = new JButton("I'm a Swing button!"); label = new JLabel(labelPrefix + "0 "); label.setText(labelPrefix + numClicks); JFrame frame = new JFrame("SwingApplication");
Puedes ver Soportar Tecnologías Asistivas para más información sobre cómo asegurarte de que tu programa funciona bien con herramientas que usan el API de accesibilidad para pedir componentes.