OutOfMemoryError:jtable保存为Image时的Java堆空间

时间:2014-08-07 16:27:36

标签: java jtable bufferedimage

目前我正在使用以下方法将jtable保存为jpeg,当jtable的维度变为2590,126181时,java.lang.OutOfMemoryError:Java堆空间异常发生在" BufferedImage构造函数",当表格的大小很小,图像成功保存。

 public BufferedImage saveComponentAsJPEG(JTable table, String filename) {
   Dimension size = table.getSize();
   BufferedImage myImage = 
     new BufferedImage(size.width, size.height,
     BufferedImage.TYPE_INT_RGB);
   Graphics2D g2 = myImage.createGraphics();
   table.paint(g2);  
   return myImage;    
 } 

如何在pdf或jpeg图像中保存更大尺寸的jtable?

1 个答案:

答案 0 :(得分:0)

更新信息:

你问如何将JTable分成不同的小图像":

当您浏览下面的代码时,请阅读我的评论,它们有助于解释正在发生的事情,并将帮助您更好地理解如何将JTable / JComponent绘制到许多小图像上。我的代码与您的代码类似,但有两个关键点:

1)我创建了一个小的图像,然后多次使用,而不是创建一个大的BufferedImage,因此留下的内存占用非常小。

2)使用单个图像,我每次都使用Graphics.translate()来绘制JTable的一小部分。

以下代码使用大型JComponents(2590 x 126181)和瓷砖大小200x200进行测试,整个过程不超过60mb的内存:

//width = width of tile in pixels, for minimal memory usage try 200
//height = height of tile in pixels, for minimal memory usage try 200
//saveFileLocation = folder to save image tiles
//component = The JComponent to save as tiles
public static boolean saveComponentTiles(int width, int height, String saveFileLocation, JComponent component)
{   
    try
    {
        //Calculate tile sizes
        int componentWidth = component.getWidth();
        int componentHeight = component.getHeight();
        int horizontalTiles = (int) Math.ceil((double)componentWidth / width); //use (double) so Math.ceil works correctly.
        int verticalTiles = (int) Math.ceil((double)componentHeight / height); //use (double) so Math.ceil works correctly.
        System.out.println("Tiles Required (H, W): "+horizontalTiles+", verticalTiles: "+verticalTiles);

        //preset arguments
        BufferedImage image;

        //Loop through vertical and horizontal tiles
        //Draw part of the component to the image
        //Save image to file
        for (int h = 0; h < verticalTiles; h++)
        {
        for (int w = 0; w < horizontalTiles; w++)
        {
            //check tile size, if area to paint is smaller than image then shrink image
            int imageHeight = height;
            int imageWidth = width;
            if (h + 1 == verticalTiles)
            {
            imageHeight = componentHeight - (h * height);
            }
            if (w + 1 == horizontalTiles)
            {
            imageWidth = componentWidth - (w * width);
            }
            image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_ARGB);
            Graphics g = image.getGraphics();

            //translate image graphics so that only the correct part of the component is panted to the image
            g.translate(-(w * width), -(h * height));
            component.paint(g);

            //In my example I am saving the image to file, however you could throw your PDF processing code here
            //Files are named as "Image.[h].[w]"
            //Example: Image 8 down and 2 accross would save as "Image.8.2.png"
            ImageIO.write(image, "png", new File(saveFileLocation + "Image." + h +"."+ w + ".png"));
            //tidy up
            g.dispose();
        }
        }
        return true;
    }
    catch (IOException ex)
    {
        return false;
    }
}

就这样称呼它:

boolean result = saveComponentTiles(200, 200, saveFileLocation, jTable1);

此外,如果您尚未完成此操作,则只应从different thread调用该方法,因为它会在处理大型组件时挂起您的应用程序。


如果您尚未选择PDF库,我强烈建议您查看iText


原帖:

  

您正在寻找的过程非常简单,但可能需要一些工作。

     

你正在考虑部件的正确轨道,但作为大卫   提到你不应该混淆jTable,而是你需要一个   使用TiledImage课程,或自己做一些事情   RenderedImageRasters

     

这种方法基本上使用HDD空间而不是内存和   然后,您可以在许多较小的零件/瓷砖中创建大图像   完成后,您可以将其全部保存到单个图像文件中。

     
     

这个答案也可能有所帮助:https://stackoverflow.com/a/14069551/1270000