g.drawImage()仅渲染图像在JPanel上可见的部分,还是“牢记"?图片的其余部分? [英] Does g.drawImage() render only the part of the image visible on a JPanel, or does it "keep in mind" the rest of the image?

查看:161
本文介绍了g.drawImage()仅渲染图像在JPanel上可见的部分,还是“牢记"?图片的其余部分?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我们有以下代码:

(在扩展JPanel的类中):

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

如果dx1dy1为负数或dx2dy2大于JPanel的宽度(换句话说,部分图像将不在屏幕上),则调整渲染的内容,使其仅关注"在JPanel上可见的部分?我对此感到好奇,因为如果在JPanel上绘制非常大的图像,paintComponent()可能会变慢.

If dx1 and dy1 are negative or dx2 and dy2 are larger than the width of the JPanel (in other words, part of the image will be off-screen), does drawImage() adjust what is rendered so that it only "pays attention to" the part visible on the JPanel? I am curious about this because if I draw a very large image on the JPanel, paintComponent() could get slow.

推荐答案

这里有问题的两个方面……

There are two sides of the problem here...

1.加载大图像

在代码示例中,您已经将一张大图像加载到内存中(直接将其绘制到组件上).这意味着,如果您将拥有一个非常大的图像,那么当您开始将其加载到内存中对其进行绘制时(无论如何都没关系),您将遇到第一个问题-它会消耗大量的内存完全加载后.

You already have a large image loaded into memory in your code example (you are painting it directly onto the component). That means if you will have a really big image - you will encounter first problems when you will start loading it into memory to paint it (doesn't really matter how) - it will consume a lot of memory when fully loaded.

当您处理大型图像时,这应该是主要的麻烦,因为标准Java并没有提供很多工具.您只能使用基本工具加载完整图像.

This should be the main headache when you work with large images as standard Java doesn't provide a lot of tools. You may only load full image using the basic tools.

您可能想研究一些其他方法来加载图像的一部分(不确定是否总是可能的)或将大图像拆分为多个部分,然后仅加载显示的图像部分.诸如JAI之类的第三方库可能对此有所帮助.

You might want to look into some alternative ways of loading part of image (not sure that it is always possible) or splitting large image into parts and loading only displayed image parts. 3rd party libraries like JAI might help with that.

无论如何,这就是所有歌词"-让我们转到您所问的第二个问题.

Anyway, that is all "lyrics" - let's go to the second problem you asked about.

2.在组件上绘制大图像

我敢打赌,您已经阅读了一些Swing教程,并且您可能已经知道该剪辑了.您可能还知道,通常将其设置为组件的当前 visible 范围.是的,只有可见部分.

I bet you have read some Swing tutorials and you might be aware of the clip. You might also know that is usually set to component's current visible bounds. Yep, only visible part.

因此,如果您使用的面板尺寸为5000x5000 px,并在其上绘制了5000x5000 px的图像,但是面板的可见部分仅为500x500 px-图像也将被基础图形剪裁,并且仅适合于剪辑将被绘制.

So if you have something like panel with 5000x5000 px size with 5000x5000 px image painted on it, but the visible part of the panel is only 500x500 px - image will also be clipped by the underlying graphics and only the part that fits the clip will be painted.

此优化还适用于各种形状的绘画/填充以及其他带有图形的操作.这不是显而易见的事情,但在大多数情况下,绘制完整的形状/图像更好,并让基础图形优化绘制操作.在大多数情况下,这要比手动剪切形状/图像并绘制结果快很多倍.

This optimization also works for various shapes painting/filling and other operations with graphics. Its not an obvious thing but in most cases it is better to paint full shape/image and let the underlying graphics optimize the painting operation. In most cases that will be times faster then to clip shape/image manually and paint the result.

另一件事-将图像绘制到图形上是Graphics2D中最快的操作之一,因此我不会真正关注它.

One more thing - drawing an image onto the graphics is one of the fastest operations in Graphics2D so i wouldn't really focus on it.

您可以查看以下小示例,该示例清楚地指示了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.

只需运行此示例并调整框架的大小即可更改组件的可见区域以查看输出.每次重涂都会显示纳秒级的绘画时间-视可见区域的大小而定.

Simply run this example and resize the frame to change component's visible area to see output. It will display painting time in nanoseconds for each repaint - it will vary a lot depending on the visible area size.

这篇关于g.drawImage()仅渲染图像在JPanel上可见的部分,还是“牢记"?图片的其余部分?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆