In addition to reducing flicker, a backbuffer can be used to store the accumulated results of drawing operations. We can easily implement a canvas-and-brush applet:
import java.applet.*; import java.awt.*; import java.awt.event.*; public class Brush1 extends Applet implements MouseMotionListener { int width, height; Image backbuffer; Graphics backg; public void init() { width = getSize().width; height = getSize().height; backbuffer = createImage( width, height ); backg = backbuffer.getGraphics(); backg.setColor( Color.black ); backg.fillRect( 0, 0, width, height ); backg.setColor( Color.white ); addMouseMotionListener( this ); } public void mouseMoved( MouseEvent e ) { } public void mouseDragged( MouseEvent e ) { int x = e.getX(); int y = e.getY(); backg.fillOval(x-5,y-5,10,10); repaint(); e.consume(); } public void update( Graphics g ) { g.drawImage( backbuffer, 0, 0, this ); } public void paint( Graphics g ) { update( g ); } }
Click and drag over the applet to paint:
Another example:
import java.applet.*; import java.awt.*; import java.awt.event.*; public class Keyboard3 extends Applet implements KeyListener, MouseListener { int width, height; int x, y; String s = ""; Image backbuffer; Graphics backg; public void init() { width = getSize().width; height = getSize().height; setBackground( Color.black ); x = width/2; y = height/2; backbuffer = createImage( width, height ); backg = backbuffer.getGraphics(); backg.setColor( Color.black ); backg.fillRect( 0, 0, width, height ); backg.setColor( Color.green ); addKeyListener( this ); addMouseListener( this ); } public void keyPressed( KeyEvent e ) { } public void keyReleased( KeyEvent e ) { } public void keyTyped( KeyEvent e ) { char c = e.getKeyChar(); if ( c != KeyEvent.CHAR_UNDEFINED ) { s = s + c; backg.drawString( s, x, y ); repaint(); e.consume(); } } public void mouseEntered( MouseEvent e ) { } public void mouseExited( MouseEvent e ) { } public void mousePressed( MouseEvent e ) { } public void mouseReleased( MouseEvent e ) { } public void mouseClicked( MouseEvent e ) { x = e.getX(); y = e.getY(); s = ""; repaint(); e.consume(); } public void update( Graphics g ) { g.drawImage( backbuffer, 0, 0, this ); g.setColor( Color.gray ); g.drawLine( x, y, x, y-10 ); g.drawLine( x, y, x+10, y ); } public void paint( Graphics g ) { update( g ); } }
Click and type; click again and type some more:
A third example:
import java.applet.*; import java.awt.*; import java.awt.event.*; import java.lang.Math; public class Brush2 extends Applet implements MouseMotionListener { int width, height; Image backbuffer; Graphics backg; int mx, my; double t = 0; public void init() { width = getSize().width; height = getSize().height; mx = width / 2; my = height / 2; backbuffer = createImage( width, height ); backg = backbuffer.getGraphics(); backg.setColor( Color.black ); backg.fillRect( 0, 0, width, height ); backg.setColor( Color.white ); addMouseMotionListener( this ); } public void mouseMoved( MouseEvent e ) { } public void mouseDragged( MouseEvent e ) { int x = e.getX(); int y = e.getY(); int dx = x - mx; int dy = y - my; t += Math.sqrt( dx*dx + dy*dy ) / 20; if ( t > 2*Math.PI ) { t -= 2*Math.PI; } backg.drawLine( x, y, x+(int)(15*Math.cos(t)), y+(int)(15*Math.sin(t)) ); mx = x; my = y; repaint(); e.consume(); } public void update( Graphics g ) { g.drawImage( backbuffer, 0, 0, this ); } public void paint( Graphics g ) { update( g ); } }
Programming a custom brush and canvas enables experimentation with behaviors not otherwise possible. An understanding of arithmetic, geometry, and trigonometry will enhance your own ability to "play" in this medium.