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 !!!
luinziAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Jan LouwerensSoftware EngineerCommented:
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
0
JodCommented:
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 
0
JodCommented:
Now animating...

jlouwere's code above is nearly there but requires a few fixes to work...but I know this does work:


 import java.applet.*;
 import java.awt.*;
 import java.awt.image.*;
 import java.net.*;

 public class Animation extends Applet {
   Image []  img;
   int     index = 0;
   MediaTracker tracker;

   public void init() {
     img = new Image[4];  // 4 images in animation
     tracker = new MediaTracker(this);

   }

   public void start() {
     try {
       // images loading
       for (int i = 0; i < img.length; i++) {
         img[i] = getImage(new URL(getDocumentBase(), "george"+i+".jpg"));
         tracker.addImage(img[i],0);        
        }

       tracker.waitForAll();
       
     } catch (Exception e) {
       e.printStackTrace();
     }
     
     AnimationThread at = new AnimationThread();
     at.delayedAnimation(this, 500);
     at.start();
   }

   public void paint(Graphics g) {
     if (img[0] != null) {
       g.drawImage(img[index % img.length],0,0,this);
     }
   }

   public void animate() {
     repaint();
     index++;
   }

   class AnimationThread extends Thread {
     Animation animationApplet;
     int delay;

     public void delayedAnimation(Animation a, int delay) {
       this.animationApplet = a;
       this.delay = delay;
     }

     public void run() {
       while (true) {
         try {
           sleep(delay);
           animationApplet.animate();
         } catch (Exception e) {
           e.printStackTrace();
         }
       }
     }
   }
 }


As you can see there are a lot of changes here from your code and unfortunately all of them are necessary but this will load your 4 graphics files and display them one after the other.

(I have not put the double buffering into this code but it is not strictly necessary here...you should see the graphics just fine for now)

The speed of the animation is controlled by this line of code:

at.delayedAnimation(this, 500);

make the 500 smaller to show the graphics faster or make it bigger to show them more slowly.

Also look here for the most up to date way of doing this:

http://java.sun.com/docs/books/tutorial/uiswing/painting/animation.html

This uses swing and there are a number of good reasons to use swing. But that's another question entirely...

If you have any questions, let me know
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
luinziAuthor Commented:
Jods abnswer was the most comprehensible and well explained. Thank you very much for your help Jod, the points are yours
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java

From novice to tech pro — start learning today.