2010-02-18 5 views
5

Je me demande si SwingWorker doit être une classe imbriquée dans mon interface graphique principale. Je préfèrerais en faire une classe externe pour garder l'interface graphique claire de n'importe quelle logique de mes programmes.Est-ce que SwingWorker doit être une classe imbriquée?

J'ai essayé de rendre la classe SwingWorker external, ce qui fonctionne bien pour le processus, malheureusement, je ne peux accéder à aucun de mes champs GUI de la classe SwingWorker. Chaque fois que j'essaie d'accéder à un attribut, tel qu'une étiquette ou autre, à partir de la méthode done() de SwingWorker, j'obtiens une exception nullPointer.

Un conseil serait grandement apprécié!


Tout d'abord, merci beaucoup Jeff! Fonctionne très bien jusqu'ici, même si je ne pouvais pas vous suivre sur la deuxième option que vous avez présentée. Une de mes tâches d'arrière-plan calcule une certaine taille (valeur longue), donc ce serait bien d'obtenir cette valeur à partir de mon interface graphique.

Vous avez suggéré de travailler avec des getters et setters mais malheureusement je n'ai aucune idée sur la façon de les implémenter dans la classe SwingWorker.

Je l'ai essayé comme ceci:

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

Le compositeur est invoqué à la fin de la méthode doInBackground(). Malheureusement, je ne peux pas utiliser la méthode get() depuis mon interface graphique.

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

La création d'un objet de « w » ne fonctionne pas dans mon cas comme le constructeur exige un objet de Runnable. Ai-je raté quelque chose? S'il vous plaît allez-y doucement sur moi, c'est la première fois que je travaille avec SwingWorker. :) Encore une fois, merci beaucoup pour votre aide!

Répondre

6

Vous pouvez faire du SwingWorker une classe externe. Cependant, comme toute autre classe, si elle ne peut pas voir les variables (par exemple, l'étiquette que vous voulez définir), bien sûr, elle ne pourra pas la définir. Une chose que vous pourriez faire est de passer le travailleur à un Runnable qu'il exécute quand il est terminé.

public class MySwingWorker extends SwingWorker { 

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

maintenant de l'interface graphique, vous pouvez faire quelque chose comme

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

Cela devient un peu plus compliqué si vous voulez utiliser le résultat de la SwingWorker, bien qu'il soit possible. Plutôt que de passer le Runnable au constructeur de travailleur swing, vous avez une méthode setter et il serait alors quelque chose comme:

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

Dans les deux cas, le Runnable fonctionne de façon similaire à une fermeture qui est exécutée lorsque le travailleur est fini.

+0

Il serait également possible de simplement passer le label dans le constructeur plutôt que le runnable. Définir une nouvelle sous-classe de travailleurs pour chaque petite action serait probablement exagéré. Les cours anonymes sont parfaits pour résoudre ce problème particulier de l'assemblage d'un très petit objet étroitement couplé. –

+0

Cela dépend vraiment si c'est un cas d'utilisation unique. L'abstraction fonctionne si vous le faites dans de nombreux endroits. Oh, comment les fermetures seraient utiles. –

Questions connexes