g.drawImage()只渲染JPanel上可见的图像部分,还是“记住”图像的其余部分?

时间:2013-05-14 04:08:38

标签: java swing jpanel implementation paintcomponent

假设我们有以下代码:

(在扩展JPanel的类中):

public void paintComponent(Graphics g) {
    g.drawImage(image, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null);
}

如果dx1dy1为否定或dx2dy2大于JPanel的宽度(换句话说,部分图片)将在屏幕外),drawImage()是否会调整呈现的内容,以便它只“关注”JPanel上可见的部分?我对此感到好奇,因为如果我在JPanel上绘制一个非常大的图像,paintComponent()可能会变慢。

1 个答案:

答案 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使用任何可用的大图像路径。

只需运行此示例并调整框架大小以更改组件的可见区域以查看输出。它将显示每次重绘的绘画时间(以纳秒为单位) - 它会根据可见区域大小而变化很大。