2012-06-14 4 views
6

Ich habe eine Java-Anwendung, die einen SwingWorker verwendet, um eine Bezeichnung und eine Fortschrittsleiste in der GUI zu aktualisieren, und es funktioniert gut. Ich möchte jedoch eine Funktion zu dieser Einstellung hinzufügen.wie GUI von Swingworker zu aktualisieren, die zwei verschiedene Werte zurückgibt

Mein Swing Worker führt eine Aufgabe aus, die die Länge n hat, und wiederholt diese Aufgabe m mal. Im Moment sagt meine GUI nur, wie oft die Aufgabe wiederholt wurde, aber ich möchte, dass sie mir auch mitteilt, in welcher Länge der Aufgabe wir uns befinden. Sagen Sie n=300 und m=50, möchte ich etwas wie:

Task 49 is at 248() 
Task has been repeated 48 times 

Was soll ich in meinem SwingWorker ändern?

/** 
* 
* @author digitaldust 
*/ 
public class Model extends SwingWorker<Integer, Integer> { 

    private HashMap<String, Number> GUIparams; 
    private int session; 
    private int ticks; 

    Model(HashMap<String, Number> KSMParams) { 
     GUIparams = KSMParams; 
     session = (Integer)GUIparams.get("experimentsInSession"); 
     ticks = (Integer)GUIparams.get("howManyTicks"); 
    } 

    /** 
    * Actual simulation 
    */ 
    @Override 
    protected Integer doInBackground() throws Exception { 

     int i=0; 
     while(!isCancelled() && i<session){ 
      i++; 
      int ii=0; 
      while(!isCancelled() && ii<ticks){ 
       // this is n, the task length and I'd like to update the GUI with this value 
       ii++; 
      } 
      System.out.println(i); 
      // this is m, how many time the task has been repeated, and now it is updated in the GUI 
      publish(i); 
      setProgress(i); 
      Thread.sleep(1000); 
     } 
     return i; 
    } 

    /** 
    * Invoked when simulation exits 
    */ 
    @Override 
    protected void done() { 
     if (isCancelled()) { 
      Logger.getLogger(Model.class.getName()).log(Level.WARNING, "Experiment session cancelled by user. Closing Session..."); 
     } else { 
      // do stuff 

      Logger.getLogger(Model.class.getName()).log(Level.WARNING, "Experiment session ended."); 
     } 
    } 

} 

Antwort

7

Der zweite V-Typ-Parameter in SwingWorker<T,V> zur Durchführung Zwischen Ergebnisse dieses Swingworker der veröffentlichen und Prozessmethoden verwendet. Dies könnte Ihre benutzerdefinierte Klasse sein. Hier ist ein Beispiel, basierend auf posted SSCCE (aus Gründen der Übersichtlichkeit gekürzt):

class Progress { 
    private int task; 
    private int element; 

    public Progress(int task, int element) { 
     super(); 
     this.task = task; 
     this.element = element; 
    } 
     ... 
} 

public class Model extends SwingWorker<Integer, Progress> { 
    ... 
    @Override 
    protected Integer doInBackground() throws Exception { 
      ... 
      publish(new Progress(i, ii)); 
     } 
} 

EDIT: Beispiel für Prozessverfahren Implementierung

@Override 
protected void process(List<Progress> progressList) { 
    for (Progress p : progressList){ 
     System.out.println(p.getTask() + " : " + p.getElement()); 
    } 
} 

EDIT: Beispiel für UI Update

Hier ist eine leicht modifizierte Version der Worker-Implementierung, Simila r zu einer Probe in SwingWorker Handbuch demonstriert. Die einzigen Änderungen sind die Einführung von textArea Mitglied und aktualisiert setProgress() Anruf in doInBackground(). progress Eigenschaft wird verwendet, um die Fortschrittsleiste zu aktualisieren, process() wird verwendet, um Textbereich zu aktualisieren.

public static class Model extends SwingWorker<Integer, Progress> { 

    private HashMap<String, Number> GUIparams; 
    private int session; 
    private int ticks; 
    private JTextArea textArea; 

    Model(HashMap<String, Number> KSMParams, JTextArea textArea) { 
     GUIparams = KSMParams; 
     session = (Integer)GUIparams.get("experimentsInSession"); 
     ticks = (Integer)GUIparams.get("howManyTicks"); 

     this.textArea = textArea; 
    } 

    @Override 
    protected void process(List<Progress> progressList) { 
     for (Progress p : progressList){ 
      textArea.append(p.getTask() + " : " + p.getElement() + "\n"); 
      System.out.println(p.getTask() + " : " + p.getElement()); 
     } 
    } 

    /** 
    * Actual simulation 
    */ 
    @Override 
    protected Integer doInBackground() throws Exception { 

     int i=0; 
     while(!isCancelled() && i<session){ 
      i++; 
      int ii=0; 
      while(!isCancelled() && ii<ticks){ 
       // this is n, the task length and I'd like to update the GUI with this value 
       ii++; 
      } 
      //System.out.println(i); 
      // this is m, how many time the task has been repeated, and now it is updated in the GUI 
      publish(new Progress(i, ii)); 
      //setProgress(i); 
      setProgress(100 * i/session); 
      Thread.sleep(1000); 
     } 
     return i; 
    } 

    /** 
    * Invoked when simulation exits 
    */ 
    @Override 
    protected void done() { 
     if (isCancelled()) { 
      Logger.getLogger(Model.class.getName()).log(Level.WARNING, "Experiment session cancelled by user. Closing Session..."); 
     } else { 
      // do stuff 

      Logger.getLogger(Model.class.getName()).log(Level.WARNING, "Experiment session ended."); 
     } 
    } 
} 

Hier ist eine Demo-Initialisierung:

final JProgressBar progressBar = new JProgressBar(0, 100); 
final JTextArea textArea = new JTextArea(); 
final JButton button = new JButton("Start"); 

button.addActionListener(new ActionListener(){ 
    @Override 
    public void actionPerformed(ActionEvent e) { 
     HashMap<String, Number> map = Maps.newHashMap(); 
     map.put("experimentsInSession", 10); 
     map.put("howManyTicks", 5); 

     Model task = new Model(map, textArea); 
     task.addPropertyChangeListener(
       new PropertyChangeListener() { 
        public void propertyChange(PropertyChangeEvent evt) { 
         if ("progress".equals(evt.getPropertyName())) { 
          progressBar.setValue((Integer)evt.getNewValue()); 
         } 
        } 
       }); 
     task.execute(); 
    } 
}); 
+1

+1: gleiche Idee wie meine, aber früher. –

+0

danke für den Hinweis, nur eine Nebensache: Wie bekomme ich jetzt den Wert für die GUI? Mein Code funktioniert nicht mehr: if ("Fortschritt" .equals (evt.getPropertyName())) { progressBar.setValue ((Integer) evt.getNewValue()); showTaskLabel.setText ("Experiment" + (Integer) evt.getNewValue() + "abgeschlossen.");} Nochmals vielen Dank für die Hilfe. – user299791

+1

@SimoneGabbriellini Es sieht so aus, als ob Sie die Eigenschaft 'progress' hören. Diese Eigenschaft ist "Integer" und Sie können damit einen Fortschrittsbalken wie in Ihrem Kommentar aktualisieren. Um Zugriff auf Zwischenfortschrittsergebnisse zu erhalten, sollten Sie die 'process()' Methode überschreiben. Sehen Sie meine Bearbeitung für ein Beispiel. – tenorsax