2012-06-14 17 views
6

Mam aplikację Java, która używa SwingWorker do aktualizacji etykiety i paska postępu w GUI i działa dobrze. Chciałbym jednak dodać funkcję do tego ustawienia.jak zaktualizować GUI z swingworkera, który zwraca dwie różne wartości

Mój robot swingowy wykonuje zadanie o długości n i powtarza to zadanie m razy. W tej chwili mój GUI mówi mi tylko ile czasu zostało powtórzone, ale chciałbym, żeby również mi powiedziało, na jakim etapie pracy jesteśmy. Powiedzmy: n=300 i m=50, Chciałbym coś takiego:

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

Co powinienem zmodyfikować w moim SwingWorker?

/** 
* 
* @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."); 
     } 
    } 

} 

Odpowiedz

7

Drugi parametr typu V z SwingWorker<T,V> służy do przeprowadzania wyniki pośrednie według publikowanych i procesów METODY SwingWorker'S. To może być twoja niestandardowa klasa. Oto przykład na podstawie zamieszczonych SSCCE (skrócone dla jasności):

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: Przykład implementacji metody proces

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

EDIT: Przykład aktualizacji UI

Oto nieco zmodyfikowana wersja implementacji pracownika, simila r do próbki wykazanej w podręczniku SwingWorker. Jedyne zmiany to wprowadzenie członka textArea i zaktualizowane wywołanie setProgress() w doInBackground(). Właściwość progress służy do aktualizacji paska postępu, process() służy do aktualizacji obszaru tekstowego.

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."); 
     } 
    } 
} 

Oto inicjalizacji demo:

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: sam pomysł jak moje, ale wcześniej. –

+0

dzięki za podpowiedź, tylko pomyłka: jak mogę pobrać teraz wartość GUI? Mój kod już nie działa: if ("progress" .equals (evt.getPropertyName())) { progressBar.setValue ((Integer) evt.getNewValue()); showTaskLabel.setText ("Eksperyment" + (liczba całkowita) evt.getNewValue() + "zakończona.");} Jeszcze raz dziękuję za pomoc. – user299791

+1

@SimoneGabbriellini Wygląda na to, że słuchasz własności 'progress'. Ta właściwość to 'Integer' i można jej użyć do aktualizacji paska postępu, tak jak w swoim komentarzu. Aby uzyskać dostęp do pośrednich wyników postępu, powinieneś nadpisać metodę 'process()'. Zobacz moją edycję dla przykładu. – tenorsax

Powiązane problemy