How do my methods know what graphic g is????

Please check out this piece of code:

import java.applet.*;
import java.awt.*;

public class anim1 extends Applet  implements Runnable
{

   Image buffer;
   Graphics bufferGraphics;
   boolean shouldRun = true;

   Image imagelist[];
   int pic_counter =0; //start at 0



   public void init()
    {

        Dimension size = getSize();
        buffer = createImage(size.width, size.height);
        bufferGraphics = buffer.getGraphics();
        bufferGraphics.setColor(getBackground());

        imagelist = new Image [15];


     for (int i = 0; i < 15; i++)
      {
         imagelist[i] = getImage(getCodeBase(), "q"+ i +".jpg");
      }    
     }

public void start()
{
   shouldRun = true;
   Thread runner = new Thread(this);
   runner.start();
}


public void stop()
{
   shouldRun = false;
}



public void run()
{

   while (shouldRun)
   {

         repaint();
         try
         {Thread.sleep(200);} // I think this is right - sleep for 1 second [1000 milliseconds]
         catch(InterruptedException e){}

   }
 }

public void update(Graphics g)
{
   paint(g);
}
 
                                 
 public void paint(Graphics g)
 {

   Rectangle clipBounds = g.getClipBounds();

   bufferGraphics.setClip(g.getClip());

   bufferGraphics.fillRect(clipBounds.x, clipBounds.y, clipBounds.width, clipBounds.height);

   bufferGraphics.drawImage(imagelist[pic_counter], 50, 100, this);

   // flip buffer to screen
   g.drawImage(buffer, 0, 0, this);

   pic_counter++;
   if(pic_counter >= 15)
  do
    {
     pic_counter--;
    }
   while(pic_counter > 1);
 
 }


}

I got an expert to help me with it. It uses double buffering to display a series of pictures. Whilst reading through it to understand what was going on, i couldn't work out how the paint, and update methods, who were passed an argument called g, of type Graphics, knew what g is. Could someone please annotate my code telling me how the applet knows what g is refering to. Could you also please explain the paint method as well. Thanks
luinziAsked:
Who is Participating?
 
JodConnect With a Mentor Commented:
Hello luinzi.

Some background to help you understand...

Each AWT component has two methods called update and paint which are invoked by Java whenever a component is drawing itself.

Generally, update deals with drawing the basic component outline and parts and paint() is used for specific painting, such as you are doing.

By default, update() is called first, and update then calls paint() when it is finished.

Each component is therefore a self contained unit - once you have set up the paint method in a particular component then it is AUTOMATICALLY called by the system.

Each component has it's own paint and update methods which are called individually and only deal with redrawing that component.


When the system need to redraw an application or an applet it starts by invoking the update() method in each component which in turns call the paint() method.

When the system calls update() it provides the update method with the details of the area of the screen that the component of the screen is in - the update() method just accepts this in the form of a Graphics object.

So the basic answer is that the AWT passes in the Grphica object g and the system figures out what the valuse for g is.

Think of it in the same way as you just simply accept it when someone presses a key that the system just delivers a character to you - you don't have to worry about how the character got to you. You just accept it. Think of the Graphics object in the same way.

So g represents an area of screen.

Some comment...

   Rectangle clipBounds = g.getClipBounds();
this asks the system for the area of screen that has actually changed rather than trying to redraw the whole screen unneccesarily.

   bufferGraphics.setClip(g.getClip());
this sets your object bufferGraphics object to point to just draw in the same area as that area of the screen that has changed. bufferGraphics is a copy of what you have actually showing on screen.

   bufferGraphics.fillRect(clipBounds.x, clipBounds.y, clipBounds.width, clipBounds.height);
You know draw into this offscreen area and fill it with a rectangle

   bufferGraphics.drawImage(imagelist[pic_counter], 50, 100, this);
You then draw an image over this same area

   // flip buffer to screen
   g.drawImage(buffer, 0, 0, this);
having done all this work off screen into bufferGraphics you now copy it all into the actual on screen area by drawing it in using drawimage.

What you end up with is bufferGraphics containg an exact copy of the same area that g is pointing to on screen.

Hope this helps...

0
 
saivonCommented:
I think you should ask Pitman. :)
0
 
sgomsCommented:
some more info,

update() & paint() r methods defined under Component class. Whenever there is a change in the display..for ex: the first time the component is placed on teh screen, or its moved , or resized, or its contents r altered it needs to update its display. so the update() method is called, which goes about restoring everything, and as a part of that restoration calls paint( ).

When update( ) calls paint( ) it hands it a handle to a Graphics object that represents the surface on which you can paint. This
is important because you’re limited to the surface of that particular component and thus cannot paint outside that area, which is a good thing or else you’d be painting outside the lines.

All the components r allocated a rectangular solid area("Heavy weight components") with teh help of the native peers. Hence all the painting should be done within the allocated area.

Double buffering:

Instead of drwaing on teh screen & causing flicker during every move the entire image(or rather the entire painting) is done on a buffer & this buffer is copied(not redrawn) on to the specified area.

In ur program even if u do not have the update method the result wud be the same 'cos update() wil be inherently called.

import java.applet.*;
import java.awt.*;

public class anim1 extends Applet  implements Runnable{

            Image buffer;
            Graphics bufferGraphics;
            boolean shouldRun = true;
            Image imagelist[];
            int pic_counter =0; //start at 0
            
            public void init(){
            
                //Create a Image buffer eqivalent to the size of the applet
                        Dimension size = getSize();
                buffer = createImage(size.width, size.height);
                bufferGraphics = buffer.getGraphics();
                bufferGraphics.setColor(getBackground());
            
                imagelist = new Image [15];
            
                        //Load the images into the image array            
                         for (int i = 0; i < 15; i++){
                       imagelist[i] = getImage(getCodeBase(), "q"+ i +".jpg");
                          }    
            } //init
            
            public void start(){
                        shouldRun = true;
                        Thread runner = new Thread(this); //create an instance of the thread & start it
                        runner.start();
            }
            
            public void stop(){
                        shouldRun = false; //stop the animation
            }
            
                  
            public void run(){
            
                  while (shouldRun){
                       repaint(); //paint the image
                       try
                       {Thread.sleep(200);} // I think this is right - sleep for 1 second [1000 milliseconds]
                       catch(InterruptedException e){}
                  
                  }
       }
            
            public void update(Graphics g){
                        paint(g); //pass the graphics object of the applet to the paint method
            }
            
                                         
            public void paint(Graphics g){
                //get the boundary of the screen that has been altered
                        Rectangle clipBounds = g.getClipBounds();
                        //set the boundary of the buffer
                        bufferGraphics.setClip(g.getClip());
                        //fill the altered area with the background color in the buffer
                        bufferGraphics.fillRect(clipBounds.x, clipBounds.y,clipBounds.width, clipBounds.height);
                        //draw the image on the buffer
                        bufferGraphics.drawImage(imagelist[pic_counter], 50, 100, this);
                        //COPY the buffer to the applet screen
                        g.drawImage(buffer, 0, 0, this);
                        //move on to the next image
                        pic_counter++;
                        if(pic_counter >= 15)
                              do{
                                 pic_counter--;
                              }while(pic_counter > 1);
            } //paint
            

}

-sgoms

0
Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

 
luinziAuthor Commented:
Thanks very much once again.  One last question though. Is it the case that every graphics component you wish to paint in an applet will require its own paint and update methods, or does the single update and paint method cater for more than one component?
0
 
sgomsCommented:
every component has its own update() & paint methods. As i said update & paint r methods in java.awt.Component class.

Its not necessary to override update or paint unless u wish to do some explicit painting operation on it.

If you have a applet with 2 panels & u wish to paint a rect on each panel, then u shud have 2 classes extending Panel & override the paint method inside that.

Hope ur clear.
-sgoms
0
 
JodCommented:
The important hing to remember is that you are overriding update and paint.

By default they are already written for you, but because Java has no idea what you are going to do with the component there are two problems with this:

Firstly, the only thing Java knows to do in update is to clear the component and redraw it as it was origninally. So the default implementation (which your graphical component will inherit) looks like this:

public void update(Graphics g) {
  setColor(backgroundColor);
  fillRect(0,0,getSize().width, getSize().height);
  paint(g);
}

All it does is blank out the componenet and call paint.

By default, this is all you want a component to do - just redraw itself, but it is importatnt to override update in double buffering as you just don't need to do this. You are already redrawing the screen in your paint method and don't need to do it here as well.

So every graphics component is created for you with the ability to redraw itself - you then change the paint method to redraw it in ways other than this default way.

You could then extend your anim1 class above and it will then contain a paint method that does animation as you will inherit the changed paint method into your new class.

It's all taking advantage of the class heirarchy to provide you with these functions inherited from more general components higher up in the class heirarchy.

The best thing to do is to play with these methods to see what they are doing.

There is an excellent explanation of this in Exploring Java (as well as other books) which would be well worth getting if you are interested in really pursuing this. It has a good tutorial section that leads you through the in's and out's of designing an applet that does double buffered imaging.



0
All Courses

From novice to tech pro — start learning today.