I'm attempting to double buffer an image containing a polygon in the method paint()
using AWT. Using an Image
object for the buffering process, I set the image background to black, draw the polygon to the image and then draw the buffered image to the screen. I then call repaint()
in order to render the image again.
Unfortunately, I'm still receiving artifacts when repainting the image. What am I doing incorrectly?
EDIT: As a side note, I'm using Java 8.
EDIT 2: I'm calling repaint()
in paint()
because I need to continuously buffer the image. The polygon is meant to translate across the screen based off user input.
import java.applet.Applet;
import java.awt.*;
public class DoubleBuffer extends Applet {
int xSize = 900;
int ySize = 600;
Image bufferImage;
Graphics bufferG;
@Override
public void init() {
this.setSize(xSize, ySize);
//Double buffering related variables
bufferImage = this.createImage(xSize, xSize);
bufferG = bufferImage.getGraphics();
}
//BUFFERING DONE HERE
@Override
public void paint(Graphics g){
//drawing images to external image first (buffering)
bufferG.setColor(Color.BLACK);
bufferG.fillRect(0,0,xSize,ySize);
bufferG.setColor(Color.WHITE);
bufferG.drawRect(100, 100, 100, 100);
//draw the image and call repaint
g.drawImage(bufferImage, 0, 0, this);
repaint();
}
}
The problem is that you are not overriding update
which is the method which will be called in response to repaint
requests. For heavy-weight components, the default implementation of update
will first clear the component to the background color (may default to white) then invoke your paint
method.
As pointed out by others, you shouldn’t call repaint
from within a paint
method. You should use a Timer
.
After cleaning up, the entire class will look like:
public class DoubleBuffer extends Applet {
int xSize = 900;
int ySize = 600;
Image bufferImage;
Graphics bufferG;
Timer timer=new Timer(200, ev->repaint());
@Override
public void init() {
this.setSize(xSize, ySize);
}
@Override
public void addNotify() {
super.addNotify();
//Double buffering related variables
bufferImage = this.createImage(xSize, xSize);
bufferG = bufferImage.getGraphics();
timer.start();
}
@Override
public void removeNotify() {
super.removeNotify();
bufferImage = null;
bufferG = null;
timer.stop();
}
//BUFFERING DONE HERE
@Override
public void paint(Graphics g){
//drawing images to external image first (buffering)
bufferG.setColor(Color.BLACK);
bufferG.fillRect(0,0,xSize,ySize);
bufferG.setColor(Color.WHITE);
bufferG.drawRect(100, 100, 100, 100);
//draw the image and call repaint
g.drawImage(bufferImage, 0, 0, this);
}
@Override
public void update(Graphics g) {
// now not clearing the background as we expect paint() to fill the entire area
this.paint(g);
}
}