[ Home | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 ]

Exercise 8: Painting

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:

( You need to enable Java to see this applet. )

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:

( You need to enable Java to see this applet. )

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.

( You need to enable Java to see this applet. )