2

假设我们有以下代码:

(在扩展的类中JPanel):

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

如果dx1anddy1是负数或者dx2anddy2大于 的宽度JPanel(换句话说,图像的一部分将不在屏幕上),是否drawImage()调整渲染的内容,使其仅“注意”在JPanel?上可见的部分。我对此很好奇,因为如果我在 上绘制非常大的图像JPanelpaintComponent()可能会变慢。

4

1 回答 1

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

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

于 2013-05-14T13:47:21.607 回答