2012-06-14 19 views
6

Tengo una aplicación Java que usa un SwingWorker para actualizar una etiqueta y una barra de progreso en la GUI y funciona bien. Sin embargo, me gustaría agregar una función a esta configuración.cómo actualizar GUI desde swingworker que devuelve dos valores diferentes

Mi oscilador trabajador realiza una tarea que tiene longitud n, y repite esa tarea m veces. En este momento, mi GUI solo me dice la cantidad de tiempo que la tarea se repitió, pero me gustaría que me diga también en qué extensión de la tarea estamos. Diga n=300 y m=50, me gustaría algo como:

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

¿Qué debo modificar en mi 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."); 
     } 
    } 

} 

Respuesta

7

El segundo parámetro de tipo V en SwingWorker<T,V> se utiliza para llevar a cabo los resultados intermedios por publicar y de proceso métodos de este SwingWorker. Esta podría ser tu clase personalizada. Aquí es un ejemplo basado en SSCCE publicado (acortado para mayor claridad):

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: ejemplo de implementación del método proceso

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

EDIT: ejemplo de actualización de la interfaz

Aquí hay una versión ligeramente modificada de la implementación del trabajador, similar r a una muestra demostrada en el manual SwingWorker. Los únicos cambios son la introducción del miembro textArea y la llamada setProgress() actualizada en doInBackground(). La propiedad progress se usa para actualizar la barra de progreso, process() se usa para actualizar el área de texto.

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

Aquí es una demostración de inicialización:

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: misma idea que la mía, pero tarde. –

+0

gracias por la pista, solo una cosa menor: ¿cómo recupero ahora el valor de la GUI? Mi código ya no funciona: if ("progress" .equals (evt.getPropertyName())) { progressBar.setValue ((Entero) evt.getNewValue()); showTaskLabel.setText ("Experimento" + (Entero) evt.getNewValue() + "concluido".);} Gracias de nuevo por la ayuda. – user299791

+1

@SimoneGabbriellini Parece que estás escuchando la propiedad 'progress'. Esta propiedad es 'Entero 'y puede usarla para actualizar una barra de progreso como en su comentario. Para tener acceso a los resultados de progreso intermedios, debe anular el método 'process()'. Ver mi edición para un ejemplo. – tenorsax

Cuestiones relacionadas