java - JProgressBar 未触发 setProgress 上的 propertyChange

标签 java swing swingworker jprogressbar propertychangelistener

我读过许多关于 JProgressBar 的不同文章...包括在 Java 中发现的狡猾代码; here.

大多数人表示您需要一个 SwingWorker 来让事情正常进行,这是完全有道理的,我明白这一点。我发现当我调用 setProgress(value) 来更新进度条时,大多数时候它不会触发 propertyChange 事件。我已经检查了传递给 setProgess 的值,它每次都会发生变化,所以我不确定它是否只是触发事件太快了?请参阅下面的相关代码,任何帮助/解释将不胜感激。

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 以此调用;

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

编辑:
是的,所以我应该更好地阅读 Javadocs;

由于 PropertyChangeListener 是在事件分派(dispatch)线程上异步通知的,因此在调用任何 PropertyChangeListener 之前可能会发生对 setProgress 方法的多次调用。出于性能目的,所有这些调用都合并为一个调用,仅包含最后一个调用参数。

例如,以下调用:
setProgress(1);
setProgress(2);
setProgress(3);

可能会产生值为 3 的单个 PropertyChangeListener 通知。

即我认为 setProgress 触发得太快的假设是正确的。 ProgressMonitor 可能是更好的解决方案。

最佳答案

这不是答案,而是演示 sscce ,向您展示我的意思:

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Random;

import javax.swing.*;

public class TestProgBar {
   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            ProgBar progBar = new ProgBar();


            // **** this is key and where your code may be deficient ***
            JProgressBar prog = progBar.getProg(); 


            progBar.execute();
            JOptionPane.showMessageDialog(null, prog);
         }
      });
   }
}

class ProgBar extends SwingWorker<Void, Void> {
   private JProgressBar loginProg = new JProgressBar();

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

   public JProgressBar getProg() {
      return loginProg;
   }

   @Override
   public Void doInBackground() throws InterruptedException {
      int count = 0;
      int max = 5;
      Random random = new Random();

      // simulate uploading files
      while (count < 100) {
         count += random.nextInt(max);
         if (count > 100) {
            count = 100;
         }
         setProgress(count);
         Thread.sleep(400);
      }
      // for (Folder f : folders) {
      // 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);
   }
}

同样,这段代码工作正常,表明您加载的代码没有显示错误。您需要做进一步的工作隔离错误并将其放入代码中,以便我们可以测试它。

关于java - JProgressBar 未触发 setProgress 上的 propertyChange,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13537609/

相关文章:

java - 这个先决条件是否违反了里氏替换原则

java - JList 在自动滚动和自动选择时变坏(GUI 问题)

c# - SwingWorker 与 BackgroundWorker

java - fieldQuery(String, String) 未定义

java - 删除 JSONObject 中的引号

java - 设置边界到 JTextField

java - 窗口 8 上的进度条卡住

java - SwingWorker 中的线程安全 - 以线程安全的方式更新 JTable

java.lang.UnsatisfiedLinkError : Native method not found 错误

java - 如何验证java中的JSpinner textField设置的最小值和最大值?