假设我们有以下代码:
(在扩展JPanel
的类中):
public void paintComponent(Graphics g) {
g.drawImage(image, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null);
}
如果dx1
和dy1
为否定或dx2
且dy2
大于JPanel
的宽度(换句话说,部分图片)将在屏幕外),drawImage()
是否会调整呈现的内容,以便它只“关注”JPanel
上可见的部分?我对此感到好奇,因为如果我在JPanel
上绘制一个非常大的图像,paintComponent()
可能会变慢。
答案 0 :(得分:3)
这里有两个问题......
<强> 1。加载大图片
您已经在代码示例中将大图像加载到内存中(您将其直接绘制到组件上)。这意味着如果你有一个非常大的图像 - 当你开始将它加载到内存中来绘制它时会遇到第一个问题(并不重要) - 它会消耗很多的内存满载时。
当您处理大型图像时,这应该是主要问题,因为标准Java不提供大量工具。您只能使用基本工具加载完整图像。
您可能希望研究一些加载图像部分的替代方法(不确定它是否总是可行的)或将大图像分割成部分并仅加载显示的图像部分。像JAI这样的第三方图书馆可能对此有所帮助。
无论如何,这都是“歌词” - 让我们回答你提出的第二个问题。
<强> 2。将大图像绘制到组件上
我打赌你已经阅读了一些Swing教程,你可能会知道这个片段。您可能还知道,通常将其设置为组件的当前可见边界。是的,只有可见的部分。
因此,如果您有类似于5000x5000像素大小的面板,其上涂有5000x5000像素图像,但面板的可见部分仅为500x500像素 - 图像也将被基础图形剪切,只有适合于剪辑将被绘制。
此优化还适用于各种形状的绘画/填充和其他带图形的操作。它不是一件明显的事情,但在大多数情况下,最好是绘制完整的形状/图像,让底层图形优化绘画操作。在大多数情况下,手动剪辑形状/图像并绘制结果的速度要快一些。
还有一件事 - 在图形上绘制图像是Graphics2D中最快的操作之一,因此我不会真正专注于它。
您可以查看这个小例子,它清楚地表明了Graphics2D内部实现提供的绘画优化:
public class ImageDrawTest
{
public static void main ( String[] args )
{
final ImageIcon icon = new ImageIcon ( "C:\\large.jpg" );
JComponent c = new JComponent ()
{
protected void paintComponent ( Graphics g )
{
super.paintComponent ( g );
long time = System.nanoTime ();
g.drawImage ( icon.getImage (), 0, 0, null );
time = System.nanoTime () - time;
System.out.println ( time );
}
};
JFrame f = new JFrame ();
f.getContentPane ().setLayout ( new BorderLayout () );
f.getContentPane ().add ( c );
f.setSize ( 200, 100 );
f.setLocationRelativeTo ( null );
f.setDefaultCloseOperation ( JFrame.EXIT_ON_CLOSE );
f.setVisible ( true );
}
}
而不是
C:\\large.jpg
使用任何可用的大图像路径。
只需运行此示例并调整框架大小以更改组件的可见区域以查看输出。它将显示每次重绘的绘画时间(以纳秒为单位) - 它会根据可见区域大小而变化很大。