SwingWorker: свойство Change вызывается редко

Кажется, у меня проблема с SwingWorker. Я в основном реализовал пример кода Java, обновляющий пользовательский интерфейс из метода propertyChange() моего JFrame.

Я также скопировал сон до одной второй части в doInBackground. Это оставляет мне хорошую частоту обновления setProgress в моем Worker.

Однако событие propertyChange вызывается только один раз каждые 10 секунд. Из API я знаю, что не каждый setProgress запускает событие, и я согласен с этим, однако кажется, что это довольно медленно и слишком много событий потеряно.

При переходе в отладчик я получаю лучшую ставку, ~ один раз каждые 3 вызова setProgress

Есть идеи, почему это так медленно?

Вот части моего Кодекса:

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());
        }
}

С уважением

Jens

3 ответа

Решение

Ваша проблема вполне возможно здесь:

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

Вы проверяли, что прогресс на самом деле меняется? Лучше было бы напечатать:

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

Теперь проверьте, действительно ли значение меняется.

Упс, это определенно неправильно:

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

Не сравнивайте строки, используя ==, Использовать equals(...) или equalsIgnoreCase(...) метод вместо. Поймите, что == проверяет, являются ли два объекта одинаковыми, а это не то, что вас интересует. С другой стороны, методы проверяют, имеют ли две строки одинаковые символы в одинаковом порядке, и вот что здесь важно. Так что вместо

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

делать,

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

или же,

if ("bar".equalsIgnoreCase(fu)) {
  // do something
}
  1. читайте SwingWorker, там описаны возможные сценарии, включая примеры кода

  2. setProgress(0); а также setProgress((int)((gotSize/(getSize))*100)); должен быть вызван на EDT

  3. вывод из следующих методов может быть сделан на EDT во время doInBackground()

    • process()

    • publish()

    • setProgress()

  4. самый сложный пример кода от @trashgod о PropertyChangeListener

  5. для лучшей помощи, скорее отправьте SSCCE

Вы можете попробовать запустить изменения свойств вручную:

setProgress(1);
firePropertyChange("progress", 0, 1);
Другие вопросы по тегам