Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to update GUI from swingworker which returns two different values

I have a Java app that uses a SwingWorker to update a label and a progress bar in the GUI and it works nice. However, I'd like to add a feature to this setting.

My swing worker performs a task which has length n, and it repeats that task m times. Right now my GUI just tells me how many time the task has been repeated, but I'd like it to tell me also at what length of the task we are in. Say n=300 and m=50, I'd like something like:

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

What should I modify in my 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.");
        }
    }

}
like image 690
user299791 Avatar asked Jun 14 '12 14:06

user299791


Video Answer


1 Answers

The second type parameter V in SwingWorker<T,V> is used for carrying out intermediate results by this SwingWorker's publish and process methods. This could be your custom class. Here is an example based on posted SSCCE (shortened for clarity):

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: example of process method implementation

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

EDIT: example of UI update

Here is a slightly modified version of the worker implementation, similar to a sample demonstrated in SwingWorker manual. The only changes are introduction of textArea member and updated setProgress() call in doInBackground(). progress property is used to update the progress bar, process() is used to update text area.

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

Here is a demo initialization:

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();
    }
});
like image 157
tenorsax Avatar answered Oct 12 '22 23:10

tenorsax