2012-06-14 14 views
6

Ho un'app Java che utilizza SwingWorker per aggiornare un'etichetta e una barra di avanzamento nella GUI e funziona bene. Tuttavia, vorrei aggiungere una funzione a questa impostazione.come aggiornare la GUI da swingworker che restituisce due valori diversi

Il mio operatore di swing esegue un'attività che ha la lunghezza n e ripete quell'attività m volte. In questo momento la mia interfaccia grafica mi dice solo quante volte l'attività è stata ripetuta, ma mi piacerebbe dirmi anche a che lunghezza del compito ci troviamo. Dì n=300 e m=50, vorrei qualcosa del tipo:

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

Che cosa dovrei modificare nel mio 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."); 
     } 
    } 

} 

risposta

7

Il secondo parametro di tipo V in SwingWorker<T,V> viene utilizzato per effettuare risultati intermedi da pubblicare ed elaborare i metodi di questa SwingWorker. Questa potrebbe essere la tua classe personalizzata. Ecco un esempio basato su SSCCE inviato (abbreviato per chiarezza):

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: esempio di implementazione del metodo processo

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

EDIT: esempio di aggiornamento UI

Ecco una versione leggermente modificata dell'implementazione del lavoratore, simila r su un campione dimostrato nel manuale SwingWorker. Le uniche modifiche sono l'introduzione del membro textArea e la chiamata setProgress() aggiornata in doInBackground(). La proprietà progress viene utilizzata per aggiornare la barra di avanzamento, process() viene utilizzata per aggiornare l'area di testo.

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

Ecco un'inizializzazione 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: stessa idea mia, ma prima. –

+0

grazie per il suggerimento, solo una piccola cosa: come posso recuperare ora il valore per la GUI? Il mio codice non funziona più: if ("progress" .equals (evt.getPropertyName())) { progressBar.setValue ((Integer) evt.getNewValue()); showTaskLabel.setText ("Esperimento" + (intero) evt.getNewValue() + "concluso.");} Grazie ancora per l'aiuto. – user299791

+1

@SimoneGabbriellini Sembra che tu stia ascoltando la proprietà 'progress'. Questa proprietà è 'Integer' e puoi usarla per aggiornare una barra di avanzamento come nel tuo commento. Per ottenere l'accesso ai risultati intermedi del progresso, è necessario sovrascrivere il metodo 'process()'. Vedi la mia modifica per un esempio. – tenorsax

Problemi correlati