Domanda

Mi chiedo se SwingWorker deve essere una classe annidata nel mio GUI principale. Preferirei rendono una classe esterna per mantenere l'interfaccia grafica chiara da uno qualsiasi dei programmi mia logica.

Ho cercato di rendere la classe SwingWorker esterna, che funziona bene per il processo, purtroppo non posso accedere a qualsiasi dei miei campi GUI dalla classe SwingWorker. Ogni volta che provo ad accedere ad un attributo, ad esempio come un marchio o qualsiasi altra cosa dal di dentro il metodo done() di SwingWorker ottengo un'eccezione nullpointer.

Qualche consiglio sarebbe molto apprezzato!


Prima di tutto vi ringrazio molto Jeff! Funziona bene finora, anche se non si potuto seguire sulla seconda opzione hai presentato. Una delle mie attività in background calcola una certa dimensione (valore a lungo), quindi sarebbe bello avere quel valore dalla mia GUI.

È suggerito di lavorare con getter e setter, ma purtroppo ho la minima idea su come implementarle nella classe SwingWorker.

Ho cercato in questo modo:

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

Il setter viene richiamata al termine del metodo doInBackground(). Purtroppo non riesco a utilizzare il metodo get() dal mio GUI.

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

La creazione di oggetti di "w" non funziona nel mio caso come il costruttore richiede un oggetto di Runnable. Mi sto perdendo qualcosa? Si prega di andare facile su di me, è la prima volta che lavoro con SwingWorker. :) Anche in questo caso, vi ringrazio molto per il vostro aiuto!

È stato utile?

Soluzione

È possibile effettuare lo SwingWorker una classe esterna. Tuttavia, proprio come qualsiasi altra classe, se non riesce a vedere le variabili (ad esempio, l'etichetta che si desidera impostare), ovviamente non sarà in grado di impostarlo. Una cosa che potreste fare è passare il lavoratore un Runnable che viene eseguito quando è 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(); }
 }

Ora dalla GUI, si potrebbe fare qualcosa di simile

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

Questo diventa un po 'più complicato, se si desidera utilizzare il risultato del SwingWorker, anche se è possibile. Invece di passare il Runnable al costruttore del lavoratore swing, si avrebbe un metodo setter e allora sarebbe qualcosa di simile:

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

In entrambi i casi, il Runnable funziona in modo simile a una chiusura che viene eseguito quando il lavoratore è terminato.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top