Link to home
Start Free TrialLog in
Avatar of luinzi
luinzi

asked on

Double buffering with applets! Oh yeah and my code doesn't work!!!

I am using JDK 1.2 and am trying to program an applet to perform an recursive loop so that it calls various jpg files and displays them continuously looping in the applet. I have created a list of jpgs from which a picture is called, and then displayed in the paint method.

I have two problems: 1stly my code does not work. It only appears to display the 1st image.

Secondly I wish to incorporate double buffering into the code so that the applet becomes flicker free.

Here is my current code. Please suggest any modifications to achieve the above. I can only really give the points to a solution that solves both these problems and explains them. Thank you very much, I look forward to  reading any solutions anyone has.

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

public class anim1 extends Applet
{
 Image imagelist[];
 int pic_counter =1;

 public void init()
 {

   imagelist = new Image [4];

   for (int i = 0; i < 4; i++)
    {
     imagelist[i] = getImage(getCodeBase(), "George"+pic_counter+".jpg");
     repaint();
     pic_counter++;
    }  
  }

 
  public void paint(Graphics g)
  {
   g.drawImage(imagelist[i], 50, 100, this);
  }

}

Since I'm offering 200 points for what to an expert would be a trivial problem can I please have modifications made to my code! Thanks !!!
Avatar of Jan Louwerens
Jan Louwerens
Flag of United States of America image

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 [4];

     for (int i = 0; i < 4; i++)
     {
         imagelist[i] = getImage(getCodeBase(), "George"+ 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();
         sThread.leep(1000); // I think this is right - sleep for 1 second [1000 milliseconds]
   }
 }

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)l

//    g.drawImage(imagelist[i], 50, 100, this);

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

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

   pic_counter++;
   if (pic_counter > 3)
      pic_counter = 0;
 }

}




// This code is untested, but should be enough to get you started
Avatar of Jod
Jod

The easier question first - how to do double buffering...

This is a general purpose graphics routine that does graphics buffering for you.

public void update(Graphics g) {
  Graphics offgc;
  Image offscreen = null;
  Rectangle box = g.getClipRect();
 
  // create the offscreen buffer and associated Graphics
  offscreen = createImage(box.width, box.height);
  offgc = offscreen.getGraphics();
 
  // clear the exposed area
  offgc.setColor(getBackground());
  offgc.fillRect(0, 0, box.width, box.height);
  offgc.setColor(getForeground());
 
  // do normal redraw
  offgc.translate(-box.x, -box.y);
  paint(offgc);
 
  // transfer offscreen to window
  g.drawImage(offscreen, box.x, box.y, this);
  offscreen = null;
  offgc = null;
}

The general idea is to only draw what you need to draw and to draw it in an offscreen buffer.

You then copy the whole buffer to the actual screen in one go after you have changed it.

In the context of a full applet, the above code should really be changed to not allocate a new Image and graphics object every time it is used, but this is an optimisation you can fiddle with.

This code not only double buffers the screen but uses the function getClipRect to only draw the parts of the window that need to be drawn - this function returns what is known as a "bounding box" and everything that may have changed will be within this area.

(Don't worry about how it does this - it is told by the operating system so just accept it and use it:)

Often this area will be much smaller than the whole window, so it saves redrawing areas of the screen that have not changed.

You can look here for more information and some more examples:

http://www.inria.fr/koala/jml/java/tricks/double-buffering.html 
ASKER CERTIFIED SOLUTION
Avatar of Jod
Jod

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of luinzi

ASKER

Jods abnswer was the most comprehensible and well explained. Thank you very much for your help Jod, the points are yours