我正在开发一个Java程序,它接收大量文件(最多3000个),并带有1/0的关联数组。目前我有一个数组的可视化,其中有一个网格,其中每个框填充黑色为1或白色为0.当绘制它运行良好但需要大约一分钟来完全加载(并可能同时锁定计算机。有没有办法可以:1,在完成之前不显示窗口
(即JFrame创建,
//绘制窗口
frame.setVisible(真))
和2,跟踪进程的进度,以便我可以使用进度条吗?
编辑:我可以运行一个线程来绘制它,然后简单地创建一个while循环,只有在线程完成后才显示它吗?
答案 0 :(得分:3)
在下面的示例中,SwingWorker
根据从随机文件中读取的数据设置BufferedImage
中的像素。请注意,Thread.sleep()
用于模拟延迟;否则不需要。您可以添加JProgressBar
,如图所示here。
有没有更好的方法来获得简单的彩色框?
是。在下面的示例中,每个像素代表一个单元格。对于较大的框,请返回图像大小的倍数,例如
@Override
public Dimension getPreferredSize() {
return new Dimension(2 * N, 2 * N);
}
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
/**
* @see https://stackoverflow.com/a/25043676/230513
*/
public class WorkerTest {
private static final int N = 256;
private final BooleanPanel panel = new BooleanPanel();
private class BooleanPanel extends JPanel {
private BufferedImage image;
public void setImage(BufferedImage bi) {
this.image = bi;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(image, 0, 0, getWidth(), getHeight(), null);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(N, N);
}
}
private class BufferedImageWorker extends SwingWorker<BufferedImage, BufferedImage> {
@Override
protected BufferedImage doInBackground() throws Exception {
BufferedImage image = new BufferedImage(N, N, BufferedImage.TYPE_INT_ARGB);
try (DataInputStream dis = new DataInputStream(
new BufferedInputStream(new FileInputStream("/dev/random")))) {
for (int row = 0; row < N; row++) {
for (int col = 0; col < N; col++) {
image.setRGB(col, row, dis.readByte() < 0 ? 0xffffffff : 0xff000000);
}
Thread.sleep(40); // ~25 Hz
publish(image);
}
return image;
}
}
@Override
protected void process(List<BufferedImage> list) {
for (BufferedImage bi : list) {
panel.setImage(bi);
panel.repaint();
}
}
}
private void display() {
JFrame f = new JFrame("WorkerTest");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(panel);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
new BufferedImageWorker().execute();
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
new WorkerTest().display();
});
}
}
答案 1 :(得分:1)
在这种情况下,我肯定会使用SwingWorker。基本上,也许是沿着这些方向的东西(我不确定你的&#39;可视化是什么类型的对象,所以为了简单起见,我只是说它是一个图像)。您可以在课程的底部添加它。您显然必须对其进行编辑以使其适合您。
protected class DrawGridTask extends SwingWorker<Image, Object> {
ObjectToPutImageOn imageObject;
public DrawGridTask(ObjectToPutImageOn obj) {
this.imageObject = obj;
}
protected Image doInBackground() {
// generate your Image or graphic or whatever here
return Image;
}
protected void done() {
imageObject.drawThisCompletedImage(get());
}
}
要调用此方法,您将运行(new DrawGridTask(objectToPutImageOn))。execute();
doInBackground()中的所有代码都将在其自己的工作线程上运行。 Done()在事件调度线程上运行,并在调用get()时获取引用doInBackground()返回。
此处提供了更多信息,包括如何在http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html
进行进度更新由于我提到过Images,如果您使用它们,您可能还想看一下MediaTracker类,这对于阻塞非常有用,直到图像准备就绪。