Java Swing:读取许多图像文件而没有内存问题?
我正在编写一个JavaSwing应用程序,它将从磁盘加载大约1500个png图像,每个图像的大小从50kb到75kb不等。我不需要一次加载所有图像,但我需要一次加载50个图像。我一直在尝试使用典型的:Java Swing:读取许多图像文件而没有内存问题?,java,user-interface,image,swing,Java,User Interface,Image,Swing,我正在编写一个JavaSwing应用程序,它将从磁盘加载大约1500个png图像,每个图像的大小从50kb到75kb不等。我不需要一次加载所有图像,但我需要一次加载50个图像。我一直在尝试使用典型的: new javax.swing.ImageIcon(getClass().getResource("myimage.jpeg") 但是我的应用程序冻结了,在大约前30幅图像之后,我的内存就用完了 加载这些映像的最佳方式是什么,这样我就不会使jvm过载,并且能够监视到目前为止已成功加载的映像?如果
new javax.swing.ImageIcon(getClass().getResource("myimage.jpeg")
但是我的应用程序冻结了,在大约前30幅图像之后,我的内存就用完了
加载这些映像的最佳方式是什么,这样我就不会使jvm过载,并且能够监视到目前为止已成功加载的映像?如果可能和必要的话,我不介意在加载图像时应用程序是否显示“加载…”屏幕,但我不确定如何做到这一点
缓存在这里有用吗?我不太明白,但我看到了关于使用MediaTracker的内容,我不知道如何在这里实现 如果您已经知道要加载多少个.png,您可能需要创建一个ImageIcon数组,并从目录中逐个加载它们(这将允许您显示加载…屏幕) 我认为您应该做的是在运行应用程序时增加JVM的最小/最大HeapSize。您可以通过添加-Xmx256m作为参数来指定它们(这会将最大堆设置为256MB)(也可能是-Xms32m[这会将最小堆设置为32mb]),请参阅 您可以在启动应用程序时添加这些选项(例如“java-jar myApp.jar-Xmx128m”),也可以添加到系统的jvm配置文件或项目的构建属性中 这段代码将加载整个目录;如果您只想加载50个图像,只需修改开始和停止参数即可。
如前所述,您必须将最大堆(-Xmx)设置为大约300M(例如分辨率1280x1024->1310720px->4字节/像素->5242880字节->50个图像->256MB)
File dir=新文件(“/path/to/directory”);
File[]files=dir.listFiles();
BuffereImage[]images=新的BuffereImage[files.length];
对于(int i=0;i
通过类加载器加载文件时应该非常小心,因为在类加载器处于活动状态时不会释放这些资源
而是使用另一种方法,使用java.io.File对象直接从磁盘加载文件。然后,它们就可以被丢弃,而不会被隐藏起来。为什么不为每个图像创建一个包装器对象,按需加载它们,并使用s或s呢。这样,垃圾收集器可以在必要时存储图像数据,并且可以在清除弱引用时重新加载
好处是,当需要用于其他用途时,可以清除图像的内存。缺点是,您必须在显示之前重新加载图像(或对图像执行任何操作)。您将如何处理图像?您真的需要ImageIcon实例吗,还是图像也需要?在这两种情况下,如果使用ImageIO中的同步方法而不是ImageIcon构造函数,则控制加载可能会更容易
如果您在30张图像之后已经遇到OutOfMemory错误,我假设这些图像可能具有较高的分辨率和/或颜色深度,即使它们在磁盘上相对较小。加载图像时,图像将被解压缩,并且需要比压缩文件大得多的内存(彩色图像通常为4*宽度*高度字节)。除非图像非常小,否则您可能无法在合理的内存量内缓存1500张未压缩的图像,因此您必须实施一些策略,仅加载当前需要的图像。如Tedil所述,您应该通过以下方式为应用程序提供更多内存:
java -Xmx256m -classpath yourclasspath YourMainClass
要加载带有“请等待”加载屏幕和进度条的图像是很棘手的。它已经进入了高级Swing领域。如果您使用的是Java6,我建议您阅读SwingWorker类
下面的演示向您展示了一种方法:
package com.barbarysoftware;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.util.List;
public class ImageLoadingDemo {
public static void main(String[] args) {
final JFrame frame = new JFrame();
frame.setPreferredSize(new Dimension(600, 400));
frame.getContentPane().add(new JLabel("I'm the main app frame", JLabel.CENTER));
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
final JDialog pleaseWaitDialog = new JDialog(frame, "Loading images", true);
final int imageCount = 50;
final JProgressBar progressBar = new JProgressBar(0, imageCount);
final BufferedImage[] images = loadImages(frame, pleaseWaitDialog, imageCount, progressBar);
System.out.println("images = " + images);
}
private static BufferedImage[] loadImages(JFrame frame, final JDialog pleaseWaitDialog, final int imageCount, final JProgressBar progressBar) {
final BufferedImage[] images = new BufferedImage[imageCount];
SwingWorker<Void, Integer> swingWorker = new SwingWorker<Void, Integer>() {
@Override
protected Void doInBackground() throws Exception {
for (int i = 0; i < imageCount; i++) {
System.out.println("i = " + i);
publish(i);
Thread.sleep(1000); // to simulate the time needed to load an image
// images[i] = ImageIO.read(new File("... path to an image file ..."));
}
return null;
}
@Override
protected void process(List<Integer> chunks) {
final Integer integer = chunks.get(chunks.size() - 1);
progressBar.setValue(integer);
}
@Override
protected void done() {
pleaseWaitDialog.setVisible(false);
}
};
JPanel panel = new JPanel();
panel.add(progressBar);
panel.add(new JButton(new AbstractAction("Cancel") {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}));
pleaseWaitDialog.getContentPane().add(panel);
pleaseWaitDialog.pack();
pleaseWaitDialog.setLocationRelativeTo(frame);
swingWorker.execute();
pleaseWaitDialog.setVisible(true);
return images;
}
}
package.com.barbarysoftware;
导入javax.swing.*;
导入java.awt.*;
导入java.awt.event.ActionEvent;
导入java.awt.image.buffereImage;
导入java.util.List;
公共类ImageLoadingDemo{
公共静态void main(字符串[]args){
最终JFrame=新JFrame();
frame.setPreferredSize(新尺寸(600400));
frame.getContentPane().add(新的JLabel(“我是主应用程序框架”,JLabel.CENTER));
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(空);
frame.setVisible(true);
最终JDialog pleaseWaitDialog=新JDialog(帧,“加载图像”,true);
最终int imageCount=50;
最终JProgressBar progressBar=新的JProgressBar(0,imageCount);
final BuffereImage[]images=加载图像(帧,请编辑对话框,图像计数,进度条);
System.out.println(“images=“+images”);
}
私有静态缓冲区映像[]加载映像(JFrame框架、最终JDialog pleaseWaitDialog、最终int imageCount、最终JProgressBar progressBar){
最终BuffereImage[]图像=新BuffereImage[imageCount];
SwingWorker SwingWorker=新SwingWorker(){
@凌驾
受保护的Void doInBackground()引发异常{
对于(int i=0;ipackage com.barbarysoftware;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.util.List;
public class ImageLoadingDemo {
public static void main(String[] args) {
final JFrame frame = new JFrame();
frame.setPreferredSize(new Dimension(600, 400));
frame.getContentPane().add(new JLabel("I'm the main app frame", JLabel.CENTER));
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
final JDialog pleaseWaitDialog = new JDialog(frame, "Loading images", true);
final int imageCount = 50;
final JProgressBar progressBar = new JProgressBar(0, imageCount);
final BufferedImage[] images = loadImages(frame, pleaseWaitDialog, imageCount, progressBar);
System.out.println("images = " + images);
}
private static BufferedImage[] loadImages(JFrame frame, final JDialog pleaseWaitDialog, final int imageCount, final JProgressBar progressBar) {
final BufferedImage[] images = new BufferedImage[imageCount];
SwingWorker<Void, Integer> swingWorker = new SwingWorker<Void, Integer>() {
@Override
protected Void doInBackground() throws Exception {
for (int i = 0; i < imageCount; i++) {
System.out.println("i = " + i);
publish(i);
Thread.sleep(1000); // to simulate the time needed to load an image
// images[i] = ImageIO.read(new File("... path to an image file ..."));
}
return null;
}
@Override
protected void process(List<Integer> chunks) {
final Integer integer = chunks.get(chunks.size() - 1);
progressBar.setValue(integer);
}
@Override
protected void done() {
pleaseWaitDialog.setVisible(false);
}
};
JPanel panel = new JPanel();
panel.add(progressBar);
panel.add(new JButton(new AbstractAction("Cancel") {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}));
pleaseWaitDialog.getContentPane().add(panel);
pleaseWaitDialog.pack();
pleaseWaitDialog.setLocationRelativeTo(frame);
swingWorker.execute();
pleaseWaitDialog.setVisible(true);
return images;
}
}