Search code examples
javaimagedoublebuffergraphic

Java Graphics and Image explanation?


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!


Solution

  • 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