JProgressBar不会在setProgress上触发propertyChange

我已经阅读了许多关于JProgressBar的不同文章……包括在Java上找到的狡猾的代码; 这里。

大多数人表示你需要一个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;

因为PropertyChangeListeners在Event Dispatch Thread上异步通知,所以在调用任何PropertyChangeListener之前,可能会对setProgress方法进行多次调用。 出于性能目的,所有这些调用仅与最后一个调用参数合并为一个调用。

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

可能会导致单个PropertyChangeListener通知值为3。

IE我的假设是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 { 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); } } 

同样,这段代码工作正常,表明你加载的代码没有显示错误。 您需要做进一步的工作来隔离错误并将其转换为代码,以便我们对其进行测试。

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

因为PropertyChangeListeners在Event Dispatch Thread上异步通知,所以在调用任何PropertyChangeListener之前,可能会对setProgress方法进行多次调用。 出于性能目的,所有这些调用仅与最后一个调用参数合并为一个调用。

例如,以下调用:
setProgress(1);
setProgress(2);
setProgress(3);
可能会导致单个PropertyChangeListener通知值为3。

IE我的假设是setProgress射击太快是正确的。 ProgressMonitor可能是更好的解决方案。 我已经用SSCCE和我的程序证实了这一点,两者都只是过快地触发setProgress,因此,只有传递给setProgress的最后一个值被传递给PropertyChange事件。

如果你想立即调用监听器,你可以尝试以下(这对我有用):

 setProgress(1); firePropertyChange("progress", 0, 1);