I've recently started doing some tutorials in simple game making stuff.
so far it's been pretty basic stuff I can wrap my head around or already understood. However I've just done a tutorial on double buffering - http://youtu.be/4T3WJEH7zrc
Anyway, the piece of code i'm having trouble understanding is this:
public void paint(Graphics g) {
dbImage = createImage(getWidth(), getHeight());
dbg = dbImage.getGraphics();
paintComponent(dbg);
g.drawImage(dbImage, 0, 0, this);
}
public void paintComponent (Graphics g) {
g.fillOval(x, y, 15, 15);
repaint();
}
So you create an image of the window, and then a graphic of that image (not too sure what the difference is there and couldn't find a simple enough definition to be satisfied with). you then pass the image into the 2nd method which creates an oval and then the window is updated via repaint (i'm pretty sure). Then finally, back in paint, the image is drawn.
So if someone could explain the flow of info to me and the difference between a graphic vs an image and the repaint command I'd be super thankful - cheers!
This is a basic example of what's known as double buffering. Instead of painting directly to the device (via the Graphics
context), you first render everything to a buffer (the dbImage
in this case) and paint everything you need to it.
Once you are done, you render the resulting image to Graphics
context of the device, in a single paint step. This reduces flickering when making lots of changes over a small period of time.
dbImage = createImage(getWidth(), getHeight());
"Creates an off-screen drawable image to be used for double buffering", see Component#createImage
for more details.
dbg = dbImage.getGraphics();
Get's the images Graphics
context. This is a unified API for painting, which makes it easy to draw to multiple different sources, such as the screen, printing or, in this, images
paintComponent(dbg);
Off loads the painting to another method, which, as you say, draws a oval
g.drawImage(dbImage, 0, 0, this);
Renders the result to the screen
The example is a little poor.
You should avoid calling repaint
or any method that might cause repaint
be to called from in any paint
method as this will cause paint
to be called again, which can quickly spiral out of control.
Also, you should dispose of any Graphics
context that you create.
I would consider something like...
Image dbImage = createImage(getWidth(), getHeight());
dbg = dbImage.getGraphics();
paintComponent(dbg);
dbg.dispose()
g.drawImage(dbImage, 0, 0, this);
to be a slightly better example
Also I've just realised, nowhere else in my code are those methods called.... how are they just called for no reason?
See Painting in AWT and Swing for an explantion of how painting works
Updated based on additional comments
Generally, it's a bad idea to paint directly to top level containers, like JFrame
or JPanel
. Instead, you should use something like JPanel
and override there paintComponent
method.
Swing components are already double buffered, so you don't need to worry to much about it.
See Performing Custom Painting for more details