如何有效地缩放 JFrame 的内容 Java?
How do you efficiently scale a JFrame's content Java?
我正在寻找一种方法来正确缩放(几乎)所有 JFrame 的内容。到目前为止,我尝试过的所有解决方案都在渲染速度方面存在巨大不足。我正在寻找的速度类似于您在智能手机上缩放内容时的速度。
JFrame 的内容应该可以快速重新缩放并保持缩放,即使您用新内容过度绘制 JFrame 也是如此。它还应该足够灵活,以便让您选择要重绘的 BufferedImage(这基本上是我正在绘制的唯一类型,我不绘制任何其他 "shapes")。我正在使用普通图形进行绘制,resp。 Graphics2D 对象。
我之前尝试过的是 Graphic2D 的缩放方法并使用 AffineTransformat 对象单独缩放每个 BufferedImage:
g.scale(scalingFactorX, scalingFactorY);
或者:
BufferedImage img = someImageToScale();
AffineTransform scaleTransform = AffineTransform.getScaleInstance(scalingFactorX, scalingFactorY);
AffineTransformOp bilinearScaleOp = new AffineTransformOp(scaleTransform,
AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
return bilinearScaleOp.filter(img, new BufferedImage(targetWidth, targetHeight,
BufferedImage.TYPE_INT_ARGB));
其中 scalingFactorX/Y 是内容应该缩放的因素和 targetWidth,resp。 targetHeight 表示 BufferedImage 的结果(缩放)尺寸。
这两种方法都相当慢,这似乎是因为在这两种情况下,每一帧,内容的缩放版本都必须重新计算。我觉得我在这里遗漏了一些非常明显的东西。
虽然 drawImage()
可以对图像重新采样,但它必须这样做 每次 paintComponent()
被调用。按照建议 here, AffineTransformOp
lets you choose the interpolation type; use the fastest one that meets your image quality requirements. Once you've satisfactorily resampled an image, ensure that you do not inadvertently resample the image a second time when rendering in a particular Graphics
context. Override getPreferredSize()
to make the destination component the same size as the resampled image, as shown in these examples.
My images are only 32x32, but there are a large amount of them (~500).
考虑使用 flyweight pattern to render only visible images. JTable
and JList
are examples, as outlined here。
Are there performance benefits or other advantages to using separate components?
您可能需要制作原型并 profile 才能确定,或许可以通过比较代表性示例:
典型的基于组件的示例包括引用的基于按钮的游戏 here, or the chess games examined here, here and here。
基于图块的 game cited here 说明了一个图块面板和多个附件面板,它们都听一个常见的游戏模型。
我正在寻找一种方法来正确缩放(几乎)所有 JFrame 的内容。到目前为止,我尝试过的所有解决方案都在渲染速度方面存在巨大不足。我正在寻找的速度类似于您在智能手机上缩放内容时的速度。
JFrame 的内容应该可以快速重新缩放并保持缩放,即使您用新内容过度绘制 JFrame 也是如此。它还应该足够灵活,以便让您选择要重绘的 BufferedImage(这基本上是我正在绘制的唯一类型,我不绘制任何其他 "shapes")。我正在使用普通图形进行绘制,resp。 Graphics2D 对象。
我之前尝试过的是 Graphic2D 的缩放方法并使用 AffineTransformat 对象单独缩放每个 BufferedImage:
g.scale(scalingFactorX, scalingFactorY);
或者:
BufferedImage img = someImageToScale();
AffineTransform scaleTransform = AffineTransform.getScaleInstance(scalingFactorX, scalingFactorY);
AffineTransformOp bilinearScaleOp = new AffineTransformOp(scaleTransform,
AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
return bilinearScaleOp.filter(img, new BufferedImage(targetWidth, targetHeight,
BufferedImage.TYPE_INT_ARGB));
其中 scalingFactorX/Y 是内容应该缩放的因素和 targetWidth,resp。 targetHeight 表示 BufferedImage 的结果(缩放)尺寸。
这两种方法都相当慢,这似乎是因为在这两种情况下,每一帧,内容的缩放版本都必须重新计算。我觉得我在这里遗漏了一些非常明显的东西。
虽然 drawImage()
可以对图像重新采样,但它必须这样做 每次 paintComponent()
被调用。按照建议 here, AffineTransformOp
lets you choose the interpolation type; use the fastest one that meets your image quality requirements. Once you've satisfactorily resampled an image, ensure that you do not inadvertently resample the image a second time when rendering in a particular Graphics
context. Override getPreferredSize()
to make the destination component the same size as the resampled image, as shown in these examples.
My images are only 32x32, but there are a large amount of them (~500).
考虑使用 flyweight pattern to render only visible images. JTable
and JList
are examples, as outlined here。
Are there performance benefits or other advantages to using separate components?
您可能需要制作原型并 profile 才能确定,或许可以通过比较代表性示例:
典型的基于组件的示例包括引用的基于按钮的游戏 here, or the chess games examined here, here and here。
基于图块的 game cited here 说明了一个图块面板和多个附件面板,它们都听一个常见的游戏模型。