Step 3: Color and the Graphics Routines

Color makes life interesting, so we'll add some colors to PaintApp. Specifically, we'll set the colors of the foreground, background, and the border of the drawing area. Later, PaintApp will allow the user (i.e. the one building the Web page) to change these colors using applet parameters, but for now, these values will be hard-coded into the program.

To keep things simple, PaintApp will only support a single drawing color.

We use three private fields to store these colors, named backColor, foreColor, and borderColor. These are all objects of class Color. Add the following line marked blue to the Fields section of PaintApp:

//
// Fields
//

private Dimension size;
private Color backColor, foreColor, borderColor;

private Image drawImage;
private Graphics gDraw;

The fields are set to their initial values in the init() method. Add the marked lines below:

public void init() {
	size = size();

	backColor = getBackground();
	foreColor = Color.black;
	borderColor = Color.black;

	clearImage();
}

The Applet class's getBackground() method returns the background color, and we assign this to backColor. We then set foreColor and borderColor to black. Color.black is a constant defined in the Color class.

We also need to change our clearImage() method to use these colors. Add the marked lines below:

private void clearImage() {
	drawImage = createImage(size.width, size.height);
	gDraw = drawImage.getGraphics();
	gDraw.setColor(backColor);
	gDraw.fillRect(0, 0, size.width, size.height);
	gDraw.setColor(borderColor);
	gDraw.drawRect(0, 0, size.width - 1, size.height - 1);
	gDraw.setColor(foreColor);
}

What does all this mean?

clearImage in Detail

We finally get to use some graphics routines! After the drawing buffer is created, we draw the background and the border. This is where gDraw, our Graphics object linked to the drawing buffer, comes into play. We'll be setting the drawing color and drawing rectangles. Obviously, we need to tell Java where to draw them! The Graphics class provides methods that let us draw onto it.

Look at these lines:

gDraw.setColor(backColor);
gDraw.fillRect(0, 0, size.width, size.height);

Using the Graphics class's setColor() method, the first statement sets the drawing color of gDraw to the background color. Then it draws a filled rectangle, using fillRect(), that covers the entire applet area. The rectangle's origin is at (0, 0), the upper-left corner, and its size is equal to the size of the applet, which we previously stored in size.

Then next two lines then draw the border:

gDraw.setColor(borderColor);
gDraw.drawRect(0, 0, size.width - 1, size.height - 1);

We set the drawing color to the border color, and then draw a hollow rectangle that stretches from the upper-left corner to the lower-right corner. We need to subtract one from each dimension; otherwise, the right and lower edges of the rectangle would wind up one pixel too far outside the applet area, and they wouldn't show up. (We didn't need to subtract one when we filled the rectangle.)

Finally, we set the drawing color to the foreground color, in preparation for some scribbling:

gDraw.setColor(foreColor);

Modifying Drawing Behavior

There is a change we need to make to the way Java paints our applet. Add the following methods after the init() method:

public void paint(Graphics g) {
	g.drawImage(drawImage, 0, 0, null);
}

public void update(Graphics g) { // Override-don't erase background
	paint(g);
}

The paint() method is where all our drawing to the screen takes place. This method is called whenever the applet needs to be redrawn. It has a single argument, a Graphics object. Whatever is drawn onto this object appears on the screen.

Here, we simply call the Graphics class's drawImage() method to copy our entire drawing buffer onto the screen. The drawImage() method draws the given Image object with its upper-left corner at the given coordinates, which in this case is (0, 0). Don't worry about the last argument now; just pass null.

We also need to override the update() method, or change its behavior. Java calls the update() method whenever the applet needs repainting. Normally, update() clears the applet area and then calls paint(). In PaintApp, though, this will cause flickering as the applet is erased and then repainted repeatedly. As shown in the code above, we leave out the erase part and simply call paint(). This is a handy technique whenever you use drawing buffers.

You can compile PaintApp now and test it. You should see a rectangle with a black border. In the next step, we'll finally get to draw something!


1