4

我的应用程序基本上是一个照片浏览器。我的方法(不要评判我,我是java新手)是ArrayList填充BufferedImages然后将图像添加到JList(左侧)。

这就是我获得图像的方式:

private void getFullImage() {

        BufferedImage im = null;        


        ImageReader imageReader = null;
            try {
                System.out.println("Loading "+original+"...");
                String suffix = Utils.getFileExt(original.getName(), "jpg");
                @SuppressWarnings("rawtypes")
                Iterator readers = ImageIO.getImageReadersBySuffix(suffix);
                imageReader = (ImageReader)readers.next();
                imageReader.setInput(new FileImageInputStream(original));
                im = imageReader.read(0);
                imageReader.dispose();
            } catch (Exception e)
            {
                e.printStackTrace();
            }

        this.img = im;
    }

然后,在我获取所有数据后,我会将图像添加到我的JList

   Vector vector = new Vector();
   JPanel container = null;
   PhotoPanel pp = null;
   Photo p = null;
   for(int i=0;i<files.length;i++)
   {
        p = new Photo(files[i]);
        pp = new PhotoPanel(p);
        container = new JPanel(new BorderLayout());
        container.add(pp,BorderLayout.CENTER);
                                       container.setBorder(BorderFactory.createTitledBorder(p.getTitle()));
                                vector.addElement(container);
  }
   plist.setListData(vector);

例如,如果我有 10 个文件,则该应用程序运行良好。问题是当我有更多图像要显示时。然后我会得到一个例外:Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space。所以,我知道我的方法很糟糕,我想知道我应该如何拍摄和存储所有图像并将它们显示在JList. 也许使用缓存?我读了一些关于SoftReference但我真的不知道如何使用它。谢谢。

4

2 回答 2

5

问题的主要可能原因有两个:


第一个,在你的情况下,我发布的更多是警告而不是实际原因,是在控制台上打印了过多的数据,带有System.out.println().

我不确定它是否只发生在 NetBeans 或所有开发工具中。但无论哪种方式,它都需要大量的打印才能触发它,我怀疑你加载了那么多文件。

无论如何,如果您使用该行的意图System.out.println("Loading "+original+"...");是用于永久/生产日志记录,而不是出于开发/调试目的而暂时放入代码中,那么您最好使用适当的Logger. 您可以在此 SO 答案中阅读 TL;DR 版本的说明,您可以通过此处提供的链接进一步阅读,包括官方文档。


另一个原因,当然是你的,是你同时加载了太多的数据。解决方案是:

  1. 缩小图像(制作缩略图),并仅显示所选图像的全尺寸版本。请注意强硬,这是一种快速的解决方法,不推荐!因为系统可能仍然无法承受。
  2. 仅加载显示在界面可见部分的图像(或所述图像的缩略图,以获得组合的最佳解决方案),并在导航界面时加载新图像(并卸载其他图像)。
于 2012-04-16T13:20:19.887 回答
0

我在处理大图像时遇到了很多困难(尽管在 SWT 中),而那些 OutOfMemory 和 NoMoreHandles(即使没有足够的内存也可能发生)是一场噩梦。我认为没有办法保留大图像或在内存中有很多图像。我同意 Andrew 的评论,但只是想补充一点,根据您的要求,您可以尝试扩展画布(或 Swing 中的任何内容)并直接在其上绘制图像,而不将它们保存在内存中(类似于 PaperClips#打印预览)。当然,您需要进行一些计算才能正确布局图像,但我认为,在这种情况下,您可能会克服内存问题(但会遇到一些其他问题:))

于 2012-04-16T13:45:57.320 回答