我正在制作一个界面,其中包含绘制的图像,该图像的尺寸应尽可能大,同时在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)
据我所知,除了适当调整图像大小外,我没有做任何奇怪的事情。但是,似乎此操作是导致此问题的原因。谁能提供一些关于如何更好地实现这一目标的指导?
答案 0 :(得分:0)
我最终使用了一个小的解决方法来防止在调整组件大小时重新绘制。我在相关组件中添加了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
布尔值:如果为true,则paintComponent
会早返回。
这不是最好的修复程序,因此我仍然希望有更好的答案,但是在我的情况下,这是可以接受的修复程序。
编辑:上面的修复程序可能对其他人也有用,但这不是根本问题。
问题出在我计算fittingImageSize
的方式上。如果宽度除以组件的高度大于高度除以组件的宽度,则返回错误的fittingImageSize
,导致应用尝试创建宽度为几百万像素的BufferedImage 。最终导致内存异常。