加载图像时 JProgressBar 不会在 for 循环中更新

JProgressBar doesnt update in for-loop when loading images

我正在编写一个小工具来对大量图像应用一些滤镜。我想在加载图像时添加一个进度条。 为此,我在这里编写了这个简单的代码:

            //Set up Progressbar 
            int pictureCount = 0;
            for (File file : chooser.getSelectedFile().listFiles(isImage)) {
                pictureCount++;
            }
            progressBar.setMinimum(0);
            progressBar.setMaximum(pictureCount);


            //Load all the Images and updating Progressbar
            for (File file : chooser.getSelectedFile().listFiles(isImage)) {
                BufferedImage bi = ImageIO.read(file);
                tilesNew.add(bi);
                progressBar.setValue(progressBar.getValue() + 1);
            }

不幸的是,进度条仅在循环结束时更新。所以它一直显示 0%,然后在程序加载所有图像几秒钟后直接显示 100%。

到目前为止我已经尝试使用 frame.revalidate()frame.repaint()Thread.sleep() 在循环中。都没有成功。

好久没用Swing了, 但似乎您在使用 GUI.

的任何平台上都经常发现一些错误

您的代码似乎在 main (UI) 线程.

中读取大文件

UI会在主线程不忙的时候更新。 但是,主线程在处理图像时会一直很忙。

您应该创建一个新的 Thread,它处理文件和图像,然后创建的线程应该将它传递给主线程以在每次 [=11] 时更新 UI =] 需要更新。

这里是 Swing 中支持多线程的一些助手:
https://stackabuse.com/how-to-use-threads-in-java-swing/

这是一个使用 JProgressBar 的快速演示。

  • 我使用计时器来模拟做一些工作。
  • 更新进度条时,会调用 ChangeListener 并重新绘制。
  • 确保您没有在 EDT 中阅读文件和更新进度条。
import java.awt.Dimension;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.Timer;

public class ProgressBarDemo extends JPanel {
    JFrame frame;
    final static int WIDTH = 200;
    final static int HEIGHT = 30;

    public ProgressBarDemo() {
        frame = new JFrame();
        setPreferredSize(new Dimension(WIDTH, HEIGHT));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(this);
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        new ProgressBarDemo().startUp();
    }

    public void startUp() {
        JProgressBar p = new JProgressBar(0, 100);

        // every 200 milliseconds, add one to the JProgressBar
        Timer t =
                new Timer(200, (ae) -> p.setValue(p.getValue() + 1));

        // invoked when the JProgressBar changes.  Calls repaint.
        p.addChangeListener((ce) -> frame.repaint());
        add(p);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        t.start();
    }
}