Search code examples
javaswingswingworkerjprogressbar

How to update a progress bar from a method inside SwingWorker


I'm trying to update a progress bar and I can't do it. My code is something like this:

public class MyWorker extends SwingWorker<Void, Void> {

    public Void doInBackground(){
        howMany=Integer.parseInt(textField.getText());
        String result=longMethod(howMany);
        label.setText("Hello, you have "+result);
 }
}

        public class Event implements ActionListener{
    public void actionPerformed(ActionEvent e){
        label2.setText("Whatever");     
        button.setEnabled(false);
        myWorer.addPropertyChangeListener(this);
        myWorker.execute();
    }

    public void propertyChange(PropertyChangeEvent event){
        if("progress".equals(event.getPropertyName())){
           int currentPercent = (int)event.getNewValue();
            progressBar.setValue(currentPercent);
        }
    }
}

So I can't use setProgress in doInBackground since the updating is made by longMethod() which is the method containing a big slow loop, placed in another class. I've made something similar passing from that method a variable to the class which contains the JFrame and then offering the possibility to see that progress if you click another button.

I don't know if there is some way of making that button (or text field) refresh itself every X seconds without clicking it or a way to use the setProgress from the method longMethod()

Thank you!


Solution

  • What you need is some way for longMethod to return progress information.

    You could, for example, create a simple interface which you could pass to longMethod which would, when it knows, update the progress...

    public interface ProgressMonitor {
        /**
         * Passes the progress of between 0-1
         */
        public void progressUpdated(double progress);
    }
    

    Then in your doInBackground method, you would pass an instance of the ProgressMonitor to the longMethod

    public class MyWorker extends SwingWorker<Integer, Integer> {
        public Integer doInBackground(){
            // It would be better to have obtained this value before
            // doInBackground is called, but that's just me...
            howMany=Integer.parseInt(textField.getText());
            String result=longMethod(howMany, new ProgressMonitor() {
                public void progressUpdated(double progress) {
                    setProgress((int)(progress * 100));
                }
            });
            //label.setText("Hello, you have "+result);
            publish(result);
            return result;
        }
    
        protected void process(List<Integer> chunks) {
            label.setText("Hello, you have "+chunks.get(chunks.size() - 1));
        }
    }
    

    This is esstenially an example of the observer pattern

    Now, if you can't modify longMethod, then you have no means by which you can update the progress, because you have no way of knowing what the longMethod is doing...