¿Cómo convierto mis programas a Swing?

El primer foco cuando se convierte un programa basado en el AWT 1.1 a Swing es modificar el programa para que use los componentes Swing en vez de los componentes AWT. Esta página explica los pasos para hacer esto. Cada paso se aplica a todos los programas -- aplicaciones y applets -- a menos que se especifique lo contrario.

Paso 1: Guardad una copia del programas basado en el AWT.

Necesitares una copia de todos los ficheros del programa, incluyendo los ficheros .java y .class. Necesitamos estas copias por varias razones:
  • Cualquier usuario que no pueda ejecutar programas Swing necesitará ejecutar el viejo programa AWT.
  • Necesitaremos referirinos al código fuente durante el proceso de conversión.
  • Después de la conversión, deberemos ejecutar las dos versiones del programa para compararlos.
  • Después de la conversión, podemos comparar el código fuente de ambas versiones para aplicar lo que hemos aprendido en otros programas que necesitemos convertir.

Paso 2: Eliminar cualquier sentencia java.awt.

Este paso pone el compilador a trabajar por nosotros. Es útil eliminar todas las importaciones del AWT incluso si nuestro programa todavía utiliza clases AWT -- como sus controladores de distribución -- porque, sin estas sentencias, el compilador generará erroees "not found" por cada componente AWT usado en nuestro programa y el número de línea donde es utilizado. Esto ayuda a localizar cada uno de los componentes AWT usado por nuestro programa para que podamos reemplazarlos por su equivalente Swing en el Paso 8, luego añadiremos las importaciones para las clases AWT que realmente necesitemos.

Paso 3: Si nuestro programa es un applet, eliminar cualquier sentencia java.applet

No necesitamos la vieja clase Applet ni el paquete java.applet, porque nuestros applets Swing será una subclase de la clase JApplet de Swing. Por eso debemos eliminar cualquiera de estas sentencias de nuestro programa:
import java.applet.Applet;
    o
import java.applet.*;

Paso 4: Importar el paquete principal Swing.

Añadir la siguiente sentencia import a nuestro programa:
import javax.swing.*;
Esto importa todos los componentes Swing además de algunas otras clases Swing. Si queremos podemos ser más meticulosos y añadir una sentencia import por cada clase Swing que utilicemos.

Paso 5: Cuidado con el problemas con los Threads!

Antes de continuar, recuerda este echo importante: Aunque el AWT es seguro ante los Threads, Swing no lo es. Debemos tener esto en consideración cuando convirtamos nuestros programas.

Para la mayoría de los programadores esto significa que un programa modifica los componentes Swing sólo desde dentro del thread de eventos del AWT. Los programas típicos modifican componentes desde dentro de los métodos de manejo de eventos y del método paint, que son llamados por el thread de eventos del AWT, por eso modificar un componente en esto métodos es seguro. Si nuestro programa modifica un componente en cualquier otro lugar, debemos tomar las acciones explícitas para hacerlo seguro ante los threads.

Hemos proporcionado dos páginas sobre Swing y los threads. Primero Threads y Swing proporciona una cobertura conceptual. Luego Cómo usar Threads contiene información práctica y ejemplos.

Paso 6: Cambiar cada componente AWT por su equivalente Swing más cercano.

La tabla proporcionada en la sección de recursos, Reemplazos Swing para Componentes AWT, lista cada uno de los componentes AWT y su equivalente Swing más cercano. Podemos usarla como una guía para elegir el reemplazo para cada componente Swing usado en nuestro programa.

En el mejor de los casos, el componente AWT y su reemplazo Swing son compatibles en el código y un simple cambio de nombre es todo lo que requiere. Por ejemplo, para convertir un botón del AWT por un botón Swing, sólo debemos cambiar todas las ocurrencias de Button por JButton en nuestro programa. Aquí tenemos un pequeño ejemplo de código AWT y su equivalente Swing. El código subrrayado muestra las diferencias entre los dos programas:

Código AWT Código Swing
Button button = new Button("A Button");
button.addActionListener(this);
JButton button = new JButton("A Button");
button.addActionListener(this);
Estaras contento de aprender que un gran número de componentes Swing tiene el código compatible con su pareja AWT.

En el lado contrario tenemos que no todos los componentes Swing son totalmente compatibles con los componentes AWT. Por eso, para algunos componentes AWT tendremos que re-escribir algún código cuando lo reemplazemos por un componente Swing. Además, podríamos elegir hacer cambios innecesarios para aprovecharnos de las características Swing. Por ejemplo, podríamos querer añadir una imagen a un botón, podríamos querer soportar la accesibilidad llamando al método setLabelFor sobre las etiquetas asociadas con otros componentes. Recursos de Conversión tiene más información para ayudarnos con las conversiones que requieren algo más que un simple cambio de nombre y sobre las conversiones opcionales.

Paso 7: Cambiar todas las llamadas a los métodos add y setLayout.

Los programas AWT añaden componentes y seleccionan el controlador de distribución directamente sobre el contenedor de alto nivel ( un frame, dialog, o applet). En contraste, los programas Swing añaden componentes y seleccionan el controlador de distribución sobre el panel de contenido del contenedor de alto nivel. La primera fila de la siguiente tabla muestra algún código típico AWT para añadir componentes a un frame y seleccionar su controlador de distribución. La segunda y tercera filas muestran dos diferentes conversiones Swing.

Código AWT
frame.setLayout(new FlowLayout());
frame.add(button);
frame.add(label);
frame.add(textField);
Conversión Óbvia Swing
(No hagas esto)
frame.getContentpane().setLayout(new FlowLayout());
frame.getContentPane().add(button);
frame.getContentPane().add(label);
frame.getContentPane().add(textField);
Conversión Eficiente Swing
(Haz esto)
Container contentPane = frame.getContentPane();
contentPane.setLayout(new FlowLayout());
contentPane.add(button);
contentPane.add(label);
contentPane.add(textField);

Habrás notado que el código Swing de la segunda fila llama a getContentPane múltiples veces, lo que es ineficiente si nuestro programa usa muchos componentes. El código Swing de la tercera fila mejora el código, obteniendo el panel de contenido una sóla vez, almacenándolo en una variable, y usando la variable para añadir componentes y seleccionar el controlador de distribución.

Paso 8: Usar el compilador para indicar más cambios necesarios.

Una vez modificado el código fuente como se ha indicado en los pasos anteriores, utilizaremos el compilador para intentar compilar nuestro programa.
javac MyClass.java
Durante este paso, el compilador nos está ayudando a identificar cualquier conversión que nos haya pasado por alto. No podemos esperar que el programa se compile a la primera.

El compilador puede ayudarnos:

  • Encontrando cada componente AWT que nos hayamos olvidado de convertir a su equivalente Swing. Si seguimos el paso 2 el compilador mostrará un mensaje de error como este por cada componente AWT que quede en nuestro programa.
    TextEventDemo.java:23: Class Button not found in type declaration.
    	Button button = new Button("Clear");
    	^
    
  • Identificar que clases AWT todavía necesita nuestro programa. Si hemos seguido las instrucciones del paso 2 el compilador mostrará un mensaje de error como este por cada clase AWT que todavía necesitesmos
    TextEventDemo.java:17: Class BorderLayout not found in type declaration.
    	BorderLayout layout = new BorderLayout();
    	^
    
    Las clases AWT que podríamos necesitar en un programa Swing son los controladores de distribución, Color, Dimension, Point, Insets, etc.

  • Localiza cualquier incompatibilidad de código entre los componentes AWT y si reemplazo Swing. Esto se muestra como un error del compilador sobre métodos no definidos. Por ejemplo, aunque los componentes de texto del AWT tienen un método addTextListener, los componentes de Swing no lo tienen. El compilador genera un mensaje de error como este indicando que JTextField no tiene dicho método.
    TextEventDemo.java:22: Method addTextListener(TextEventDemo. MyTextListener) not found in class javax.swing.JTextField.
    	textField.addTextListener(new MyTextListener("Text Field"));
    	                         ^
    
  • Eliminar el uso de API "obsoleto". Usamos la bandera del compilador -deprecation para obtener detalles sobre las clases o métodos obsoletos usados por nuestro programa y el número de línea donde son utilizados.
    javac -deprecation MyClass.java
    
Debemos corregir todos los errores devueltos por el compilador hasta que el programa se compile correctamente.

Paso 9: Ejecutar el programa Swing.

Usamoos el intérprete o el Applet Viewer para ejecutar nuestro programa:
java MyClass      o     appletviewer MyApplet.html
Si hemos olvidado modificar cualquier llamada a add o setLayout, lo descubriremos durante este paso. Si lo hemos hecho, el sistema runtime muestra un mensaje como este (el mensaje de error para setLayout es similar):
java.lang.Error: Do not use MultiListener.add() use MultiListener.getContentPane().add() instead
	at javax.swing.JApplet.createRootPaneException(Compiled Code)
	at javax.swing.JApplet.addImpl(Compiled Code)
	at java.awt.Container.add(Compiled Code)
	at MultiListener.init(Compiled Code)
	at sun.applet.AppletPanel.run(Compiled Code)
	at java.lang.Thread.run(Compiled Code)
Volvemos sobre el código, buscaremos cualquier add o setLayout, resolveremos el problema. compilaremos y ejecutaremos el programa de nuevo.

Paso 10: Comparar las versiones Swing y AWT.

Probablemente querramos que los programas sean similares, estén abiertos a las mejoras ofrecidas por swing y cualquier diferencia inherente en los dos GUIs.

Paso 11: Investigar otros componentes Swing.

Podríamos mejorar nuestro UI usando características sólo disponibles en componentes Swing (como las imágenes en botones) o usando componentes Swing más sofisticados no disponibles en el AWT. También podríamos reemplazar un componente escrito por nosotros mismos con un componente del propio Swing o un componente personalizado Swing. Los componentes completamente nuevos en Swing incluyen tablas, trees, color choosers, etc.

Paso 12: Limpieza!

Ahora es el momento de limpiar nuestro código. Si hemos dejado algún código para corregir alguna deficiencia o bug del AWT , es el momento de limpiarlo!

Ozito