使用绘制的 bufferedImage 调整 JFrame 大小时 Java 崩溃

标签 java swing drawing bufferedimage

我正在制作一个界面,其中包含一个尺寸尽可能大的绘制图像,同时保持 JFrame 内的纵横比。下面的代码用于实现此行为:

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);

    if (image == null) {
        return;
    }

    // Calculate what image size fits within the component's bounds
    Dimension fittingImageSize = getFittingImageSize();

    // Scale the image. We use AffineTransform as it's much faster than scaledInstance(...)
    AffineTransform at = new AffineTransform();
    at.scale(fittingImageSize.getWidth() / image.getWidth(), fittingImageSize.getHeight() / image.getHeight());
    AffineTransformOp scaleOp = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);
    BufferedImage scaledImage = new BufferedImage((int)fittingImageSize.getWidth(), (int)fittingImageSize.getHeight(), image.getType());
    scaleOp.filter(image, scaledImage);

    // Calculate the offset        
    Point offset = getImageOffset(fittingImageSize);

    // Draw the image
    Graphics2D g2 = (Graphics2D) g;
    g2.drawImage(scaledImage, offset.x, offset.y, null);
}

但是,当我调整 JFrame 大小时,出现堆空间异常:

Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space
    at java.awt.image.DataBufferInt.<init>(DataBufferInt.java:75)
    at java.awt.image.Raster.createPackedRaster(Raster.java:467)
    at java.awt.image.DirectColorModel.createCompatibleWritableRaster(DirectColorModel.java:1032)
    at java.awt.image.BufferedImage.<init>(BufferedImage.java:333)

据我所知,除了正确调整图像大小之外,我没有做任何奇怪的事情。但是,似乎此操作才是导致问题的原因。谁能提供一些指导我如何更好地解决这个问题?

最佳答案

我最终使用了一个小的解决方法来防止在调整组件大小时重新绘制。我向相关组件添加了一个 ComponentListener ,并在 componentResized 方法中执行了以下操作:

@Override
public void componentResized(ComponentEvent e) {
    isResizing = true;
    timer.cancel();
    timer.schedule(new TimerTask() {
        @Override
        public void run() {
            isResizing = false;
            revalidate();
            repaint();
        }

    }, redrawAfterResizeDelay);
}

然后,在 paintComponent 中,我防范 isResizing boolean 值:如果它为 true,则 paintComponent 会提前返回。

这不是最好的修复,所以我仍然希望得到更好的答案,但在我的情况下,这是一个可以接受的修复。

编辑:上述修复可能对其他人有效,但这不是根本问题。

问题出在我计算fittingImageSize的方式上。当组件的宽度除以高度大于组件的高度除以宽度时,则会返回错误的 fittingImageSize ,导致应用尝试创建宽度为 的 BufferedImage几百万像素。这就是最终导致内存异常的原因。

关于使用绘制的 bufferedImage 调整 JFrame 大小时 Java 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56706019/

相关文章:

flash as3 使用 curveTo 绘制一个 donut 楔形(具有内外半径的圆弧)

java - Selenium2 和 webdriver 的一个很好的工作示例

java - 使用 Java 将结果集转换为 CSV 文件

组件可见时的java事件

java - JFrame 重绘后不刷新

c - 如何直接访问显示器进行绘图

java - BeanCreationException : Error creating bean with name 'springApplicationAdminRegistrar' . InstanceAlreadyExistsException

java - 关于 GWT 中常规 servlet 的问题(在开发模式下工作,在 tomcat 中部署时不工作)

java - MouseListener 和 JTree

java - 如何创建用于绘制多边形的图形对象?