Swing y JFC (Java Foundation Classes)

Esta p�gina explica como usar el API Swing de forma segura con threads. Si nuestro programa es un applet, lo m�s seguro es construir su GUI en el m�todo init. Si nuestro programa es una aplicaci�n con el siguiente patr�n com�n estaremos seguros.

//Thread-safe example
public class MyApplication {
    public static void main(String[] args) {
	JFrame f = new JFrame(...);
        ...//Add components to the frame here...
	f.pack();
	f.setVisible(true);
	//Don't do any more GUI work here.
    }

    ...
    //All manipulation of the GUI -- setText, getText, etc. --
    //is performed in event handlers such as actionPerformed().
    ...
}

Sin embargo, si nuestro programa crea threads que realizan tareas que afectan al GUI, o manipulan un GUI ya visible en respuesta a alg�n evento del AWT, �sigue leyendo!

La Regla de los Threads
Los componentes Swing solo pueden ser accedidos por un thread a la vez. Generalmente, este thread es el que despacha los eventos.
Excepciones a la Regla
Unas pocas operaciones est�n garantizadas como seguras ante los threads.
C�mo Ejecutar C�digo en el Thread de Despacho de Eventos
Si necesitamos acceder al UI desde fuera del c�digo del despachador de eventos o de dibujo, podemos usar los m�todos invokeLater o invokeAndWait.
C�mo crear Threads
Si necesitamos crear un thread -- por ejemplo para manejar un trabajo que gasta mucho tiempo o paquetes de I/O -- podemos usar uno de los thread �tiles como SwingWorker o Timer.

.�La Regla de los Threads

La Regla de los Threads es la siguiente.

Regla: Una vez que se haya realizado un componente Swing, todo el c�digo que pudiera afectar o depender del estado de ese componente deber�a ejecutarse en el thread de despacho de eventos.

Esta regla podr�a sonar espeluznante, pero para la mayor�a de los programas sencillos, no tenemos que preocuparnos de los threads. Antes de entrar en detalles sobre c�mo escribir c�digo Swing, definiremos dos t�rminos: realizado y thread de despacho de eventos.

Realizado significa que el m�todo paint del componente haya sido o podr�a ser llamado. Un componente Swing que sea una ventana de alto nivel se realiza habiendo llamado a uno de estos m�todos sobre ella: setVisible(true), show, o (lo que podr�a sorprendernos) pack. Una vez que una ventana se ha realizado, todos los componentes que contiene est�n realizados. Otra forma de realizar un componente es a�adirlo a un componente que ya est� realizado.

El thread de despacho de eventos es el thead que ejecuta el c�digo de dibujo y de despacho de eventos. Por ejemplo los m�todos paint y actionPerformed se ejecutan autom�ticamente en el thread de despacho de eventos. Otra forma de ejecutar c�digo en el thread de despacho de eventos es usar el m�todo invokeLater de SwingUtilities.

.�Excepciones a la Regla

Existen unas pocas excepciones a la regla de que todo el c�digo que afecte a un componente Swing realizado debe ejecutare en el thread de despacho de eventos.

Unos pocos m�todos de threads seguros.
En la Documentaci�n del API Swing, los m�todos de threads seguros est�n marcados con este texto. Este m�todo es seguro ante los threads, aunque muchos m�todos Swing no lo son. Por favor lea Threads and Swing para m�s informaci�n.
Un GUI de una aplicaci�n frecuentemente puede ser construido y mostrado en el thread principal.
Mientras que no se haya realizado ning�n componente (Swing o de otro tipo) en el entorno de ejecuci�n actual, est� construir y mostrar un GUI en el thread principal de una aplicaci�n. Para ayudarnos a ver por qu�, aqu� hay un an�lisis del thread seguro de thread-safe example. Para refrescar nuestra memoria, aqu� est�n las l�neas m�s importantes del ejemplo.
public static void main(String[] args) {
    JFrame f = new JFrame(...);
    ...//Add components to the frame here...
    f.pack();
    f.setVisible(true);
    //Don't do any more GUI work here.
}
  1. El ejemplo construye el GUI en el thread principal. En general, podemos construir (pero no mostrar) un GUI en cualquier thread, mientras que no hagamos llamadas que se refieran o afecten a los componentes ya realizados.
  2. Los componentes en el GUI son realizados por la llamada a pack.
  3. Inmediatamente despu�s, los componentes el GUI son mostrados con la llamada a setVisible (o show). T�cnicamente, la llamada a setVisible es insegura porque los componentes ya han sido realizados por la llamada a pack. Sin embargo, como el programa no ha hecho visible el GUI todav�a, es sumamente contrario a que una llamada a paint ocurra antes de que retorne setVisible.
  4. El thread principal no ejecuta c�digo GUI despu�s de llamar a setVisible. Esto significa que el c�digo del GUI se mueve del thread principal al thread de despacho de eventos, y el ejemplo es, en la pr�ctica, de thread seguro.
Un GUI de un applet puede contruirse y mostrarse en el m�todo init.
Los navegadores existentes no dibujan el applet hasta despu�s de que hayan sido llamados los m�todos init y start. As�, construir el GUI en el m�todo init del applet es seguro, siempre que no llames a show() o setVisible(true) sobre el objeto applet actual.

Por supuesto, los applets que usan componentes Swing deben ser implementados como subclases de JApplet, y los componentes deben ser a�adidos al panel de contenido del JApplet, en vez de directamente al JApplet. Al igual que para cualquier applet, nunca deber�amos realizar inicializaci�n que consuma mucho tiempo en los m�todos init o start; en su lugar deber�amos arrancar un thread que realice las tareas que consuman tiempo.

Los siguientes m�todos de JComponent son seguros para llamarlos desde cualquier thread: repaint, revalidate, e invalidate.
Los m�todos repaint y revalidate envian peticiones para que el thread de despacho de eventos llame a paint y validate, respectivamente. El m�todo invalidate s�lo marca un componentes y se requiere la validaci�n de todos sus ancestros.
Oyentes que pueden ser modificados desde cualquier thread
Es siempre seguro llamar a los m�todos addListenerTypeListener y removeListenerTypeListener. Las operaciones de a�adir/eliminar no tienen ning�n efecto en el despacho de eventos,

.�C�mo Ejecutar C�digo en el Thread de Despacho de Eventos

La mayor parte del trabajo de post-inicializaci�n de un GUI naturalmente ocurre en el thread de despacho de eventos. Una vez que el GUI es visible, la mayor�a de los programas son conducidos por eventos como acciones de botones o clicks del rat�n, que siempre son manejados por el thread de despacho de eventos.

Sin embargo, algunos programas necesitan realizar alg�n trabajo de GUI no conducido por eventos, despu�s de que el GUI sea visible. Aqu� tenemos algunos ejemplos.

Programas que deben realizar una operaci�n de inicializaci�n larga antes de poder ser usados:
Esta clase de programas generalmente deber�a mostrar alg�n GUI mientras est� ocurriendo la inicializaci�n, y luego actualizar o cambiar el GUI. La inicializaci�n no deber�a ocurrir en el thread de despacho de eventos; si no el repintado y el despacho de eventos se parar�an. Sin embargo, despu�s de la inicializaci�n el cambio/actualizaci�n del GUI deber�a ocurrir en el thread de despacho de eventos por razones de seguridad con los threads.
Programas cuyo GUI debe actualizarse como resultado de eventos no-AWT:
Por ejemplo, supongamos que un programa servidor quiere obtener peticiones de otros programas que podr�an estar ejecut�ndose en diferentes m�quinas. Estas peticiones podr�an venir en cualquier momento, y resultan en llamadas a algunos de los m�todos del servidor en alg�n m�todo thread desconocido. �C�mo puede el m�todo actualizar el GUI? Ejecutando el c�digo de actualizaci�n del GUI en el thread de despacho de eventos.

La clase SwingUtilities proporciona dos m�todos para ayudarnos a ejecutar c�digo en el thread de despacho de eventos.

invokeLater:
Pide que alg�n c�digo se ejecute en el thread de despacho de eventos. Este m�todo retorna inmediatamente, sin esperar a que el c�digo sea ejecutado.
invokeAndWait:
Act�a igual que invokeLater, excepto en que este m�todo espera a que el c�digo se ejecute. Como regla, deber�amos usar invokeLater en vez de este m�todo.

Para m�s informaic�n sobre el uso de invokeLater y invokeAndWait, y otros trucos para esciribir programas multi-threads, puedes ver C�mo usar Threads.

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP
ARTÍCULO ANTERIOR