我读过很多关于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;
因为在事件调度线程上异步通知了PropertyChangeListeners,所以在调用任何PropertyChangeListener之前,可能会对setProgress方法进行多次调用。出于性能目的,所有这些调用仅合并为一个调用,仅包含最后一个调用参数。
例如,以下调用:
setProgress(1);
setProgress(2);
setProgress(3);
可能会导致单个PropertyChangeListener通知值为3.
即。我认为setProgress射击太快是正确的。 ProgressMonitor可能是更好的解决方案。
答案 0 :(得分:3)
这不是一个答案,只是一个演示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);
}
}
同样,这段代码工作正常,表明你加载的代码没有显示错误。您需要做进一步的工作隔离错误并将其转换为代码,以便我们对其进行测试。
答案 1 :(得分:0)
是的,所以我应该更好地阅读Javadocs;
因为在事件调度线程上异步通知了PropertyChangeListeners,所以在调用任何PropertyChangeListener之前,可能会对setProgress方法进行多次调用。出于性能目的,所有这些调用仅合并为一个调用,仅包含最后一个调用参数。
例如,以下调用:
setProgress(1);
setProgress(2);
setProgress(3);
可能会导致单个PropertyChangeListener通知值为3.
即。我认为setProgress射击太快是正确的。 ProgressMonitor可能是更好的解决方案。我已经用SSCCE和我的程序证实了这一点,两者都只是过快地触发setProgress,因此,只有传递给setProgress的最后一个值被传递给PropertyChange事件。
答案 2 :(得分:0)
如果您希望立即调用侦听器,可以尝试以下(对我有用):
setProgress(1);
firePropertyChange("progress", 0, 1);