5.2.3 The Canvas Class


The Canvas class represents a rectangular area to be used for displaying graphical images. It has the following paint method:
public void paint(Graphics g) {
  g.setColor(getBackground());
  g.fillRect(0, 0, width, height);
}
So, if you want to see something of interest on a canvas, you have create a subclass of Canvas and override the paint method in this subclass. In this subclass you can also override event-handling methods for mouse and keyboard events such as the methods mouseDown and mouseDrag; the Canvas class does by default nothing with them.

The following example is an applet that consists of a yellow canvas for drawing and a button to clear the drawing area.

The Applet
The Java Code

ScratchpadApplet.java
import java.applet.*;
import java.awt.*;

public class ScratchpadApplet extends Applet {
  
  Button clearButton;
  Scratchpad scratchpad;
  
  public void init() {
    // create GUI components
    clearButton = new Button("clear");
    scratchpad = new Scratchpad();
    // layout GUI components in applet
    setLayout(new BorderLayout());
    add("South", clearButton);
    add("Center", scratchpad);
  }

  public boolean action(Event evt, Object arg){
    if (evt.target == clearButton) {
      scratchpad.clear(); // clear canvas
    }
    return true;
  }

}
The two components in the example applet, viz., the button and the canvas, are laid out with a so-called BorderLayout. The scrollbar is placed in the southern region and the canvas is placed in the central position. With the components laid out in this way you get an applet which is rather pretty. In other layouts, for example in FlowLayout, the canvas would display as a very small and easily overlooked square. We shall come back to layouts in the next section.

Scratchpad.java
import java.awt.*;
import java.util.*;

public class Scratchpad extends Canvas {
  
  Vector points = new Vector();

  Scratchpad () {
    setBackground(Color.yellow);
  }
  
  public boolean mouseDown(Event evt, int x, int y) {
    points.addElement(new Point(x, y));
    return true;
  }

  public boolean mouseDrag(Event evt, int x, int y) {
    points.addElement(new Point(x, y));
    repaint();
    return true;
  }

  public boolean mouseUp (Event evt, int x, int y) {
    points.addElement(null);
    return true;
  }

  public void paint(Graphics g) {
    Enumeration e = points.elements();
    Point lastPt = null;
    while (e.hasMoreElements()) {  
      Point pt = (Point) e.nextElement();
      if (lastPt != null && pt != null) {
        g.drawLine(lastPt.x, lastPt.y, pt.x, pt.y);
      } 
      lastPt = pt;
    }
  }

  public void clear() {
    points = new Vector();
    repaint();
  }
}
For the canvas we have only changed the Java code for responding to mouse up, down and dragging. What we do is connect the point last visited by a straight line with the current point. At a mouse-up, a null object is added to the vector. We use this to skip drawing until the next mouse-down. In a later session we shall thoroughly discuss event handling. Note moreover that if the vector becomes larger, the screen will probably flicker. We will offer ways to overcome this in the section on applet graphics.