这里有两个方面的问题......
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
使用任何可用的大图像路径。
只需运行此示例并调整框架大小以更改组件的可见区域以查看输出。它将以纳秒为单位显示每次重绘的绘画时间 - 它会根据可见区域的大小而有很大差异。