javaswingswingworkerjprogressbarpropertychangelistener

JProgressBar not triggering propertyChange on setProgress


I've read many different articles about JProgressBar...including the dodgy code found over at Java; here.

Most indicate you need a SwingWorker to get things happening properly, which makes perfect sense, I understand that much. I am finding that when I call setProgress(value) to update the progressbar, it's not triggering the propertyChange event most of the time. I've checked the value I'm passing to setProgess and it definitely changes every time, so I'm not sure if it's just firing the event too quickly? Please see relevant code below, any help/explanation would be greatly appreciated.

class ProgBar extends SwingWorker
{
    public ProgBar()
    {
        addPropertyChangeListener(new PropertyChangeListener()
        {
           @Override
           public void propertyChange(PropertyChangeEvent evt)
           {
               if ("progress".equals(evt.getPropertyName()))
               {
                   int value = (Integer)evt.getNewValue();
                   System.out.println("propertyChange called with: " + value);
                   loginProg.setValue(value);
               }
           }
        });

        loginProg.setStringPainted(true);
        loginProg.setValue(0);
        setProgress(0);
    }

    @Override
    public Void doInBackground() throws InterruptedException
    {
        ...
        int count = 0;
        for (Folder f : folders)
        {
            ... // process 'f'
            setProgress((int)Math.min(((double)count/folders.length)*100.0, 100.0));
        }
        ...
        return null;
    }

    @Override
    public void done()
    {
        System.out.println("Done called.");
        setProgress(100);
        loginProg.setValue(100);
    }
}

JProgressBar called with this;

private void jButtonActionPerformed(java.awt.event.ActionEvent evt) 
{                                             
        // Create new thread to run progess bar.
        // Otherwise won't be able to update progress bar.
        ProgBar pb = new ProgBar();
        pb.execute();
    }
}    

EDIT:
Yeah, so I should have read the Javadocs better;

Because PropertyChangeListeners are notified asynchronously on the Event Dispatch Thread multiple invocations to the setProgress method might occur before any PropertyChangeListeners are invoked. For performance purposes all these invocations are coalesced into one invocation with the last invocation argument only.

For example, the following invokations:
setProgress(1);
setProgress(2);
setProgress(3);

might result in a single PropertyChangeListener notification with the value 3.

I.E. my assumption that setProgress was firing too quickly was correct. A ProgressMonitor might be a better solution.


Solution

  • Yeah, so I should have read the Javadocs better;

    Because PropertyChangeListeners are notified asynchronously on the Event Dispatch Thread multiple invocations to the setProgress method might occur before any PropertyChangeListeners are invoked. For performance purposes all these invocations are coalesced into one invocation with the last invocation argument only.

    For example, the following invokations:
    setProgress(1);
    setProgress(2);
    setProgress(3);
    might result in a single PropertyChangeListener notification with the value 3.

    I.E. my assumption that setProgress was firing too quickly was correct. A ProgressMonitor might be a better solution. I've confirmed this with the SSCCE and my program, both are simply firing setProgress too quickly and as a result, only the last value passed to setProgress is being passed through to the PropertyChange event.