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 !!!
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 !!!
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(getBackgrou nd());
offgc.fillRect(0, 0, box.width, box.height);
offgc.setColor(getForegrou nd());
// 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
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(getBackgrou
offgc.fillRect(0, 0, box.width, box.height);
offgc.setColor(getForegrou
// 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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Jods abnswer was the most comprehensible and well explained. Thank you very much for your help Jod, the points are yours
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(ge
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.g
bufferGraphics.fillRect(cl
// g.drawImage(imagelist[i], 50, 100, this);
bufferGraphics.drawImage(i
// 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