Double Buffering
The process of directly painting an image to the screen, completely erasing that image, then painting a new image in its place causes flickering. Double buffering avoids this flickering by creating an off-screen image that is later transferred to the screen.
When the user draws on the canvas, useTool() grabs the current off-screen layer and creates a Graphics2D context associated with that layer. The paint tools draw onto the Graphics2D cgBuffer and stores those changes in BufferedImage cvMem.
56 57 58 59 60 61 62 63 64 65 66 67 68 | public void useTool( int numTool, int oldX, int oldY, int newX, int newY) { // Selects specific tool cvMem = layersArray.getImageArray().get(layersArray.getcLayerNum()); // Grabs the current layer cgBuffer = (Graphics2D) cvMem.getGraphics(); // Creates the graphics context for that layer to be used in double buffering cgBuffer.setColor(menuBar.paintColor); // The y-coordinates are subtracted by the menu bar's height, because the canvas layers do not include the menu bar if (numTool == 1 ) pencil(oldX, oldY - paintLab.getMenuHeight(), newX, newY - paintLab.getMenuHeight()); else if (numTool == 2 ) brush(oldX, oldY - paintLab.getMenuHeight(), newX, newY - paintLab.getMenuHeight()); else if (numTool == 3 ) spray(newX, newY - paintLab.getMenuHeight()); } |
public void useTool(int numTool, int oldX, int oldY, int newX, int newY) { // Selects specific tool cvMem = layersArray.getImageArray().get(layersArray.getcLayerNum()); // Grabs the current layer cgBuffer = (Graphics2D) cvMem.getGraphics(); // Creates the graphics context for that layer to be used in double buffering cgBuffer.setColor(menuBar.paintColor); // The y-coordinates are subtracted by the menu bar's height, because the canvas layers do not include the menu bar if (numTool == 1) pencil(oldX, oldY - paintLab.getMenuHeight(), newX, newY - paintLab.getMenuHeight()); else if (numTool == 2) brush(oldX, oldY - paintLab.getMenuHeight(), newX, newY - paintLab.getMenuHeight()); else if (numTool == 3) spray(newX, newY - paintLab.getMenuHeight()); }
In my paint program, Graphics2D g2Frame paints the off-screen image stored in ArrayList<BufferedImage> imageArray at the index of int cLayerNum onto the screen. Instead of clearing the entire screen, update() alters the display with only the changes made.
202 203 204 205 206 207 208 209 210 211 | public void update(Graphics g) { // When repaint() is called, the update() then calls paint() // Since "default implementation of update() clears the Component's background before calling paint()", // I removed the background layers from flickering by drawing the layers here for ( int k = 0 ; k < layersArray.getImageArray().size(); k++) { g2Frame.drawImage(layersArray.getImageArray().get(k), 0 , getMenuHeight(), this ); } paint(g); } |
public void update(Graphics g) { // When repaint() is called, the update() then calls paint() // Since "default implementation of update() clears the Component's background before calling paint()", // (see http://journals.ecs.soton.ac.uk/java/tutorial/ui/drawing/update.html) // I removed the background layers from flickering by drawing the layers here for (int k = 0; k < layersArray.getImageArray().size(); k++) { g2Frame.drawImage(layersArray.getImageArray().get(k), 0, getMenuHeight(), this); } paint(g); }