سؤال

I seem to have a problem with SwingWorker. I basically implemented the Java Example Code updating the UI from the propertyChange() method of my JFrame.

I also copied the sleep up to one second part in doInBackground. This leaves me with a good update rate of setProgress within my Worker.

However the propertyChange Event is fired only once about every 10sec. I know from the API that not every setProgress fires an event, and I'm ok with that, however it seems that this is kinda slow and too many events are lost.

When stepping through in a Debugger I get a better rate, ~once every 3 calls to setProgress

Any ideas why it is so slow?

Here are the parts of my Code:

public Void doInBackground() {
    Random random = new Random();
    setProgress(0);
    float getSize=0,gotSize=0;
    while (Sync.syncing) {
        //Sleep for up to one second.
        try {
             Thread.sleep(random.nextInt(1000));
        } catch (InterruptedException ignore) {
            ignore.printStackTrace();
        }
        try{
            getSize=Main.getSyncGet();
            gotSize=Main.getSyncGot();
            System.out.println("setProgress: "+(gotSize/getSize));
            setProgress((int)((gotSize/(getSize))*100));
        }catch(Exception e){
            Main.LOGGER.log(Level.WARNING,"Error setting progress",e);
        }
    }
    return null;
}

public void propertyChange(PropertyChangeEvent evt) {
        if ("progress" == evt.getPropertyName()) {
            jpb.setValue((Integer) evt.getNewValue());
        }
}

Kind Regards

Jens

هل كانت مفيدة؟

المحلول

Your problem is quite possibly here:

System.out.println("setProgress: "+(gotSize/getSize));
setProgress((int)((gotSize/(getSize))*100));

Have you tested that the progress is actually being changed? A better println would be:

int value = (int)((gotSize/(getSize))*100);
System.out.println("setProgress: "+ value);
setProgress(value);

Now check to see if value is in fact changing.

Ooops, this is definitely wrong:

public void propertyChange(PropertyChangeEvent evt) {
        if ("progress" == evt.getPropertyName()) {
            jpb.setValue((Integer) evt.getNewValue());
        }
}

Don't compare Strings using ==. Use the equals(...) or the equalsIgnoreCase(...) method instead. Understand that == checks if the two objects are the same which is not what you're interested in. The methods on the other hand check if the two Strings have the same characters in the same order, and that's what matters here. So instead of

if (fu == "bar") {
  // do something
}

do,

if ("bar".equals(fu)) {
  // do something
}

or,

if ("bar".equalsIgnoreCase(fu)) {
  // do something
}

نصائح أخرى

  1. read SwingWorker, there are described possible scenarios, including code examples

  2. setProgress(0); and setProgress((int)((gotSize/(getSize))*100)); must be called on EDT

  3. output from folows methods could be done on EDT during doInBackground()

    • process()

    • publish()

    • setProgress()

  4. most complex code example by @trashgod about PropertyChangeListener

  5. for better help sooner post an SSCCE

You can try firing property changes manually:

setProgress(1);
firePropertyChange("progress", 0, 1);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top