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:
(Download the below file: Brush1.java)
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:
(Download the below file: Keyboard3.java)
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:
(Download the below file: Brush2.java)
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.