Uso avanzado de SwingWorker

Puede ver una versión activa de este post en mi nuevo blog. He decidido dejar de publicar en este blog por éstas razones. Su filosofía es la misma que éste, pero espero no tener los problemas que me he encontrado aquí.

En una entrada anterior vimos cómo hacer un uso básico de SwingWorker así como cuándo usarlo. Vimos que había dos métodos de recuperar el resultado de nuestros cálculos o tarea de larga duración.

Aquí veremos un uso avanzado de SwingWorker. Para ello realizaremos una sencilla aplicación que calcule los N primeros números de la serie de fibonacci, los vaya mostrando en un área de texto según los vaya calculando y mostraremos el progreso de la tarea un una barra de progreso.

La clase SwingWorker tiene la siguiente definición: SwingWorker<T, V>. En la entrada anterior vimos que la forma básica de recuperar el resultado de nuestros cálculos era a través del método get(), el cuál retorna un valor de tipo genérico T. El genérico V es el tipo de datos que admiten los métodos publish y process y es el tipo de datos en el que generaremos los resultados intermedios.

Para realizar nuestra tarea del cálculo de los números de fibonacci crearemos una clase FibonacciWorker que herede de SwingWorker y que haga uso de los métodos adecuados para notificar el progreso hecho en los cálculos. Esta notificación la haremos a través de eventos de cambios en una propiedad. Es posible utilizar PropertyChangelListeners con propiedades definidas por nosotros y utilizar el método firePropertyChange para lanzar estos eventos. Para este ejemplo utilizaremos la propiedad progress que es una propiedad que ya está enlazada por defecto. La propiedad state (indica el estado de la ejecución de la tarea: INCIADA, CANCELADA, COMPLETADA, …) también lo está.

class FibonacciWorker extends SwingWorker<List<Integer>, Integer> {
  PrimeNumbersTask(JTextArea textArea, int numbersToCalculate) {
    //initialize
  }

  @Override
  public List<Integer> doInBackground() {
    while (numbers.size <= numberstoCalculate && !isCancelled()) {
      number = nextFibonacciNumber();
      numbers.add(number);
      publish(number);
      setProgress(100 * numbers.size() / numbersToCalculate);
    }
    return numbers;
  }

  @Override
  protected void process(List<Integer> chunks) {
    for (Integer number : chunks) {
      textArea.append(number + "\n");
    }
  }

  private Integer nextFibonacciNumber(){
    //  calculate next fibonacci number and return it
  }
}

En el código anterior se han omitido detalles de implementación para no desviar la atención. Del código anterior cabe destacar la llamada a publish en la línea 11, la llamada a setProgress (línea 12) y la implementación del método process.

Mediante la llamada al método publish indicamos a SwingWorker que vaya almacenando resultados intermedios con los cuales llamará al método process, el cual hemos sobrescrito y lo usaremos para mostrar esos resultados intermedios. Es muy importante recalcar que mientras el método publish se ejecuta en el hilo (thread) del cálculo exhaustivo, el método process se invoca en el Event Dispatching Thread (EDT), y es por ello por lo que es seguro actualizar el interfaz de usuario.

Con la llamada al método setProgress() estamos indicando que se lance un evento de cambio sobre la propiedad progress (propiedad creada por defecto junto con state para la notificación de cambios en propiedades). El evento propagado incluirá entre sus datos el parámetro que recibe la función. Para mostrar ese progreso utilizaremos una barra de progreso, la cual la registraremos como interesada en recibir eventos de cambios en las propiedades de FibonacciWorker.

final JProgressBar progressBar = new JProgressBar(0, 100);
FibonacciWorker task = new FibonacciWorker(textArea, numbersToCalculate);
task.addPropertyChangeListener(
  new PropertyChangeListener() {
    public  void propertyChange(PropertyChangeEvent evt) {
      if ("progress".equals(evt.getPropertyName())) {
        progressBar.setValue((Integer)evt.getNewValue());
      }
    }
  });

En el siguiente enlace es posible ver una aplicación demostrando lo aprendido. Si se desea descargar el código fuente en forma de proyecto de NetBeans: FibonacciWorker NetBeans project.

Anuncios

Etiquetas: ,

2 responses to “Uso avanzado de SwingWorker”

  1. Dennis Andres says :

    Hola Ruben, estuve leyendo tus dos post sobre SwingWorker, me parecen muy buenos, y se nota que conoces del tema, yo he publicado un articulo similar, quisiera que lo veas para poder optimizar mi codigo.
    http://dairdev.blogspot.com/2010/10/uso-de-swingworker-en-una-aplicacion.html
    Gracias de antemano

Trackbacks / Pingbacks

  1. SwingWorker en Java 5 « Ruben ChT's Blog - 3 diciembre 2012

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: