Let's say we have the following code:
(in a class that extends JPanel
):
public void paintComponent(Graphics g) {
g.drawImage(image, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null);
}
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. Loading large images
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.
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.
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. Painting large image onto the component
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.
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.
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.
You can check this small example which clearly indicates painting optimizations provided by Graphics2D internal implementations:
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 );
}
}
Instead of
C:\\large.jpg
use any available large image path.
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.