加载图像时 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();
}
}
我正在编写一个小工具来对大量图像应用一些滤镜。我想在加载图像时添加一个进度条。 为此,我在这里编写了这个简单的代码:
//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();
}
}