2010-02-18 14 views
5

Me pregunto si SwingWorker tiene que ser una clase anidada dentro de mi GUI principal. Prefiero convertirlo en una clase externa para mantener la GUI libre de cualquiera de las lógicas de mis programas.¿SwingWorker tiene que ser una clase anidada?

Intenté hacer la clase SwingWorker externa, que funciona bien para el proceso, desafortunadamente no puedo acceder a ninguno de mis campos de GUI de la clase SwingWorker. Cada vez que intento acceder a un atributo, como una etiqueta o lo que sea, desde el método done() de SwingWorker, obtengo una excepción nullPointer.

¡Cualquier consejo sería muy apreciado!


Antes que nada muchas gracias Jeff! Funciona bien hasta ahora, aunque no pude seguirte en la segunda opción que presentaste. Una de mis tareas en segundo plano calcula un cierto tamaño (valor largo), por lo que sería bueno obtener ese valor de mi GUI.

Ha sugerido trabajar con getters y setters, pero desafortunadamente no tengo idea de cómo implementarlos en la clase SwingWorker.

me trataron así:

public void setSize(long totalSize) { 
    this.totalSize = totalSize; 
} 
public long getTotalSize() { 
    return totalSize; 
} 

El colocador se invoca al final del método doInBackground(). Desafortunadamente no puedo usar el método get() desde mi GUI.

final MySwingWorker w = new MySwingWorker(); 
Runnable r = new Runnable() { 
    public void run() { 
     // do something with w.get() 
    } 
}; 
w.setRunnable(r); 
w.execute(); 

La creación de objetos de "w" no funciona en mi caso como el constructor requiere un objeto de Ejecutable. ¿Me estoy perdiendo algo? Por favor, trátame, es la primera vez que trabajo con SwingWorker. :) ¡De nuevo, muchas gracias por su ayuda!

Respuesta

6

Puede hacer del SwingWorker una clase externa. Sin embargo, al igual que cualquier otra clase, si no puede ver las variables (por ejemplo, la etiqueta que desea establecer), por supuesto no podrá configurarlo. Una cosa que podría hacer es pasarle al trabajador un Runnable que ejecuta cuando se completa.

public class MySwingWorker extends SwingWorker { 

    private final Runnable r; 
    public MySwingWorker(Runnable r) { 
     this.r = r; 
    } 
    public void doInBackground() {...} 
    public void done() { r.run(); } 
} 

Y desde la interfaz gráfica de usuario, es posible hacer algo como

Runnable updateLabel = new Runnable() { 
     public void run() { 
      label.setText("myValue"); 
     } 
}; 
SwingWorker w = new MySwingWorker(updateLabel); 
w.execute(); 

Esto se pone un poco más complicado si desea utilizar el resultado de la SwingWorker, aunque es posible. En lugar de pasar el Ejecutable al constructor del trabajador de oscilación, que tendría un método de selección y entonces sería algo así como:

final MySwingWorker w = new MySwingWorker(); 
Runnable r = new Runnable() { 
    public void run() { 
     // do something with w.get() 
    } 
}; 
w.setRunnable(r); 
w.execute(); 

En cualquier caso, el Ejecutable funciona de manera similar a un cierre que se ejecuta cuando el trabajador Está terminado.

+0

También sería posible pasar la etiqueta en el constructor en lugar del ejecutable. Definir una nueva subclase de trabajador para cada pequeña acción probablemente sería exagerado. Las clases anónimas son excelentes para resolver este problema particular de armar un objeto muy pequeño y fuertemente acoplado. –

+0

Realmente depende si se trata de un caso de uso único. La abstracción funciona si lo haces en muchos lugares. Oh, cómo los cierres serían útiles. –

Cuestiones relacionadas