Wednesday, June 27, 2007

Chapter 14 - The java.awt Package: Painting

Chapter 14: The java.awt Package: Painting

Objectives

This chapter helps you to prepare for the exam by covering the following objectives:

Know how the AWT supports painting, repainting, and clipping operations.

.
A general knowledge of how the AWT supports painting, repainting, and clipping is required
for the certification exam.
Know how the Canvas and Graphics classes are used to implement drawing and painting
operations.

.
The Canvas and Graphics classes are fundamental to painting. You need to know the
relationship between these classes and the types of methods that are available for drawing
shapes, text, and images.
Know how text is drawn using the Font, FontMetrics, and Graphics classes.

.
The Font and FontMetrics classes are used to draw text on a Graphics object. A
general understanding of how this occurs is useful for developing painting-based applets
and applications.
Know how images are created and displayed.

.
The certification exam requires a basic understanding of how images are created and
displayed using a Graphics object.
Study Strategies

As you read through this chapter, you should concentrate on the following key items:

.
How the Canvas and Graphics classes relate to each other
.
How painting and repainting occurs
.
What types of methods are provided by the Graphics class
.
How geometric shapes are drawn using a Graphics object
.
How the Font, FontMetrics, and Graphics classes are used to draw text
.
How images are created and displayed
.
How clipping works
Chapter Introduction

The Canvas, Graphics, and Image classes of the java.awt package are fundamental to AWT
painting and drawing. You''ll learn how to use these classes to display bitmapped images and draw
geometric shapes. You'll also learn how to use the Font class to control the way text is displayed.
Understanding these classes is essential to developing GUI-based applets and applications. The
certification exam may have a few questions that will call upon your knowledge of these classes. By
studying the class descriptions of this chapter and working the programming examples, you should be
able to do well on related exam questions.

The Canvas and Graphics Classes

The Canvas class of java.awt provides a general GUI component (it extends Component) for
drawing images and text (or anything else) on the screen. It does not support any drawing methods of
its own, but provides access to a Graphics object via its paint() method.
The paint() method is invoked upon the creation and update of a Canvas object. It enables the
Graphics object associated with the Canvas object to be updated. The paint() method should not
be directly invoked, but it can be indirectly accessed using the repaint() method. The AWT creates a
background thread that automatically causes the paint() methods of Canvas, Frame, Panel,
Applet, and other GUI components as required to update any areas that need repainting. You can
implement custom drawing and painting operations in your applet or application by extending the
Canvas class and overriding its paint() method.

- 238



Note
Graphics Context A Graphics object is sometimes referred to as a graphics
context.

Note
Graphics Object A Graphics object is also available via the paint()
methods of the Applet, Frame, Panel, and other classes that extend
Component.

The Graphics class is where all the low-level drawing methods are implemented. These methods can
be used directly to draw objects and text or can be combined to display more elaborate screen objects.
The Graphics drawing methods enable you to draw and fill a number of geometrical shapes, including
lines, arcs, ovals, rectangles, rounded rectangles, and polygons. A special draw3DRect() method is
provided for drawing rectangles that are shaded to give them a three-dimensional appearance. The
Graphics class also provides the capability to draw bitmapped images and text on the canvas. Some
of the important Graphics drawing methods are as follows:

.
draw3DRect() and fill3DRect()—Draws/fills a 3D rectangle
.
drawArc() and fillArc()—Draws/fills an arc
.
drawImage()—Draws an image on the screen
.
drawLine()—Draws a line segment
.
drawOval() and fillOval()—Draws/fills an oval
.
drawPolygon() and fillPolygon()—Draws/fills a polygon
.
drawPolyline() and fillPolyline()—Draws/fills a sequence of line segments
.
drawRect() and fillRect()—Draws/fills a rectangle
.
drawRoundRect() and fillRoundRect()—Draws/fills a rounded rectangle
.
drawString()—Draws a String of text at a specified location
.
getColor() and setColor()—Gets and sets the drawing (foreground) color
.
getFont() and setFont()—Gets and sets the current font
Note
The update() Method The AWT invokes an object's update() method
(inherited from Component) when the object's repaint() method is invoked.
The update() method fills the component with its background color, set the
component's foreground color, and then invokes the component's paint()
method.

Note
The repaint() Method When an object's repaint() method is invoked, the
AWT schedules a repaint operation. Repainting typically occurs every .1 seconds.
Multiple repaint() requests that occur within this interval are combined. This
prevents repainting from consuming all the processing resources of an applet or
application.

Note
Colors Colors are available via the Color class. This class defines constants,
such as Color.red, Color.white, and Color.blue, that can be used to
identify colors by name. Colors can also be created using their red, blue, and
green color values.

We'll cover shape drawing, text drawing, and image drawing the following sections.

Drawing Shapes

Some programs, such as the Microsoft Windows Paint program, are used to construct images by
painting on the screen. These paint programs create an image array of color pixels and update the array
based on user paint commands. These commands may consist of pixel-level drawing operations or
more general operations that draw geometrical objects such as circles, rectangles, and lines. Painting
programs are characterized by the fact that the pixel array is the focus for the drawing that takes place.

Drawing programs, such as CorelDRAW, support drawing operations using a more object-oriented
approach. When you draw a circle or line with a drawing program, you do not merely update the pixels
of the canvas—you add an object to the list of objects that are displayed on the canvas. Because
drawing programs operate at a higher object level, you can select, move, resize, group, and perform
other operations on the objects that you've drawn.
The Graphics class is oriented toward providing the methods that are needed to support higher-level
drawing programs rather than lower-level painting programs. However, it does support important
painting operations, such as displaying bitmapped images, as you'll see in the ImageApp program later
in this chapter.
When using the Graphics class to support graphical operations, you will generally maintain a list of the
objects that you've drawn and use that list of objects to repaint the screen, as required.

- 239



The DrawApp Program

The DrawApp program shows how the higher-level drawing operations of the Graphics class are used
to display and maintain a list of the objects that are drawn on a canvas. The source code of the
DrawApp program is shown in Listing 14.1.

DrawappListing 14.1: The Source Code for the Program

import java.awt.*;
import java.awt.event.*;
import java.util.*;

public class DrawApp extends Frame {
// Create buttons
Button lineButton = new Button("Line");
Button ovalButton = new Button("Oval");
Button rectButton = new Button("Rectangle");
Button clearButton = new Button("Clear");
// Create Canvas object
MyCanvas canvas = new MyCanvas(TwoPointObject.LINE);
public static void main(String[] args) {

DrawApp app = new DrawApp();
}
public DrawApp() {

super("DrawApp")
;
add("Center",canvas)
;
setupButtons()
;
addWindowListener(new WindowEventHandler())
;
pack()
;
setSize(400,400)
;
show()
;


}

void setupButtons() {
// Connect event handlers

- 240



lineButton.addActionListener(new ButtonHandler())
;
ovalButton.addActionListener(new ButtonHandler())
;
rectButton.addActionListener(new ButtonHandler())
;
clearButton.addActionListener(new ButtonHandler())
;
Panel panel = new Panel()
;
panel.add(lineButton)
;
panel.add(ovalButton)
;
panel.add(rectButton)
;
panel.add(clearButton)
;
add("North",panel)
;


}
class ButtonHandler implements ActionListener
{


public void actionPerformed(ActionEvent ev)
{
// Handle button clicks
String s=ev.getActionCommand()
;
if(s.equals("Clear")) canvas.clear()
;
else if(s.equals("Line")
)


canvas.setTool(TwoPointObject.LINE)
;
else if(s.equals("Oval")
)
canvas.setTool(TwoPointObject.OVAL)
;
else if(s.equals("Rectangle")
)
canvas.setTool(TwoPointObject.RECTANGLE)
;


}
}
class WindowEventHandler extends WindowAdapter{

public void windowClosing(WindowEvent e)
{
System.exit(0)
;
}


}
}
class MyCanvas extends Canvas {

- 241



// Define the default drawing tool
int tool = TwoPointObject.LINE;
Vector objects = new Vector()
;
TwoPointObject current;
boolean newObject = false;
public MyCanvas(int toolType)
{


super()
;
tool = toolType;
// Handle mouse clicking and movement
addMouseListener(new MouseHandler())
;
addMouseMotionListener(new MouseMotionHandler())
;


}
public void setTool(int toolType)
{


tool = toolType;
}
public void clear()
{


objects.removeAllElements()
;


repaint()
;
}
public void paint(Graphics g)
{


// Draw/redraw canvas
int numObjects = objects.size()
;
for(int i=0;i{


TwoPointObject obj = (TwoPointObject) objects.elementAt(i)
;


obj.draw(g)
;
}
if(newObject) current.draw(g)
;


}
class MouseHandler extends MouseAdapter {
public void mousePressed(MouseEvent e){
// Handle mouse down

- 242



current = new TwoPointObject(tool,e.getX(),e.getY());

newObject = true;
}
public void mouseReleased(MouseEvent e){

// Handle mouse up

if(newObject)
{
objects.addElement(current)
;
newObject = false;


}

}
}
class MouseMotionHandler extends MouseMotionAdapter {

public void mouseDragged(MouseEvent e){
// Handle mouse movement
int x = e.getX();
int y = e.getY();
if(newObject) {

int oldX = current.endX;
int oldY = current.endY;
if(tool != TwoPointObject.LINE)
{


if(x > current.startX) current.endX = x;
if(y > current.startY) current.endY = y;
int width = Math.max(oldX,current.endX) - current.startX + 1;
int height = Math.max(oldY,current.endY) - current.startY + 1;
repaint(current.startX,current.startY,width,height)
;


}else{
current.endX = x;
current.endY = y;
int startX = Math.min(Math.min(current.startX,current.endX),oldX);
int startY = Math.min(Math.min(current.startY,current.endY),oldY);
int endX = Math.max(Math.max(current.startX,current.endX),oldX);

- 243



int endY = Math.max(Math.max(current.startY,current.endY),oldY);
repaint(startX,startY,endX-startX+1,endY-startY+1);
}
}
}

}
}
class TwoPointObject
{


// Encapsulates objects that can be described using two points
public static int LINE = 0;
public static int OVAL = 1;
public static int RECTANGLE = 2;
public int type, startX, startY, endX, endY;
public TwoPointObject(int objectType,int x1,int y1,int x2,int y2)
{


type = objectType;
startX = x1;
startY = y1;
endX = x2;
endY = y2;


}
public TwoPointObject(int objectType,int x,int y)
{


this(objectType,x,y,x,y)
;
}
public TwoPointObject()
{


this(LINE,0,0,0,0)
;
}
public void draw(Graphics g)
{


if(type == LINE) g.drawLine(startX,startY,endX,endY)
;


else{
int w = Math.abs(endX - startX)
;
int l = Math.abs(endY - startY)
;


- 244



if(type == OVAL) g.drawOval(startX,startY,w,l);
else g.drawRect(startX,startY,w,l);
}
}

}
Figure 14.1: The DrawApp opening window.
When you run DrawApp, you will see the opening window shown in Figure 14.1.
The DrawApp program is initially configured for you to draw lines in its window area. You can draw a
line by clicking the left mouse button and dragging the mouse. When you have finished drawing the line,
release the left mouse button and the drawn line will be completed. The coordinate where you press the
left mouse button is the beginning of the line, and the coordinate where you release the left mouse
button is the end of the line. Go ahead and draw several lines, as shown in Figure 14.2.


Figure 14.2: Drawing lines with DrawApp.
The DrawApp program supports the drawing of lines, ovals, and rectangles. Click the Oval button to
change the drawing tool to draw ovals. You draw an oval in the same way that you draw a line. When
you click the left button of your mouse, you mark the upper-left corner of an invisible bounding box
surrounding the oval. Drag the mouse to where you want the lower-right corner of the oval's bounding
box and release the left mouse button. Try drawing a few ovals, as shown in Figure 14.3.

- 245



Figure 14.3: Drawing ovals with DrawApp.
Now click the Rectangle button to begin drawing rectangles. You draw rectangles in the same way that
you draw ovals. Go ahead and draw a rectangle, as shown in Figure 14.4.


Figure 14.4: Drawing rectangles with DrawApp.

You can experiment with the program before going on to find out how it works. If you want to clear the
drawing screen, click the Clear button.
The DrawApp program is a little longer than the programs you've seen so far in this book. It consists of
three major classes and three event-handling inner classes. The DrawApp class is the main class used
to implement the program. The MyCanvas class is used to implement the program's main canvas
component. The TwoPointObject class is used to implement the line, oval, and rectangle objects that
are drawn on the screen. It is called TwoPointObject because it supports objects that can be
characterized by a starting point (mouse down) and an ending point (mouse up).
DrawApp declares the canvas variable to refer to the MyCanvas object that implements the drawing.
This object is constructed by passing the TwoPointObject.LINE constant as an argument. This tells
the constructed object that the line tool should be initially used to support drawing. The height and width
of the DrawApp window is set to 400 pixels.
The actionPerformed() method of the ButtonHandler class handles the clicking of the buttons.
The Clear button is handled by invoking the clear() method of the MyCanvas class to clear the
canvas to a blank state. The Line, Oval, and Rectangle buttons are handled by invoking the
setTool() method of the MyCanvas class to set the current drawing tool. It uses the LINE, OVAL, and
RECTANGLE constants defined in the TwoPointObject class.

MyCanvas

The MyCanvas class extends the Canvas class to provide custom drawing capabilities. The tool
variable is used to identify the current drawing tool that is in effect. The objects variable is declared as
a Vector. It is used to store all the objects drawn by the user. The current variable is used to refer to
the current TwoPointObject object being drawn by the user. The newObject flag is used to track
whether the user has begun drawing a new object.

- 246



The MyCanvas constructor invokes the constructor of the Canvas class using the superclass
constructor call statement, and then sets the tool variable to the toolType argument passed to the
constructor.
The setTool() method changes the tool used to draw an object.
The clear() method invokes the removeAllElements() method of the Vector class to remove all
drawing objects stored in the Vector referenced by the objects variable.
The paint() method is used to paint and repaint the screen. It uses the size() method of the
Vector class to determine how many objects are stored in the objects vector and sets the
numObjects variable to this value. It then iterates through each object stored in objects and draws
each one on the canvas. The elementAt() method of the Vector class is used to retrieve an object
from the objects vector. The object is cast into an object of class TwoPointObject and assigned to
the obj variable. The draw() method of the TwoPointObject class is invoked to draw the object on
the current Graphics context.
Notice that the paint() method does not have to know how to support limited area repainting. Only full
canvas painting needs to be implemented by paint(). Support of limited area repainting is provided by
the local AWT implementation.
The MouseHandler and MouseMotionHandler inner classes handle the events associated with
pressing, releasing, and dragging the mouse. They do this by extending the MouseAdapter and
MouseMotionAdapter classes of java.awt.event. The MouseHandler class handles the pressing
and releasing of the mouse button via the mousePressed() and mouseReleased() methods. The
MouseMotionHandler class handles the dragging of the mouse via the mouseDragged() method.
The mousePressed() method handles the event that is generated when the user clicks the left mouse
button in the canvas. The method is called by the Java runtime system with the position of the mouse
click. A new TwoPointObject object is created, with the tool variable and the position of the mouse
click as its arguments. The newly created object is assigned to the current variable, and the
newObject flag is set to true.
The mouseReleased() method is used to handle the event that is generated when the user releases
the left mouse button. This action marks the completion of the drawing of an object. The event is
handled by adding the object referenced by the current variable to the objects vector. The
newObject flag is then set to False. The object referenced by the current variable is updated with its
ending position during the processing of the mouseDragged() event-handling method. The
newObject flag is checked to make sure that the mouse was not clicked outside of the current window
and then released.
The mouseDragged() method performs somewhat more sophisticated event-handling than the
mousePressed() and mouseReleased() methods. It checks the newObject flag to make sure that
an object is currently being drawn. It then sets the oldX and oldY variables to the ending position of
the object being drawn. These variables will be used to determine which portion of the canvas needs to
be repainted. Repainting of the entire canvas is not visually appealing because it causes previously
drawn objects to flicker.
If the current drawing tool is not a line, then an oval or a rectangle is the object being drawn by the user.
The x,y coordinates of the mouse motion are provided via the MouseEvent argument to the
mouseDragged() method. These coordinates are checked to determine whether the mouse was
dragged below and to the right of the object being drawn. If this is the case, the ending position of the
current object is updated. If the mouse is dragged to the left or above the starting point of the object, the
current position of the mouse is ignored. This is to ensure that the starting position of the oval or
rectangle is indeed its upper-left corner. The new width and height of the area to be repainted are
calculated as the maximum area covered by the previous ending position and the current object ending
position. This is to ensure that the repaint operation will erase any previous boundaries of the object
being drawn. The max() method of the java.lang.Math class is used to determine this maximum
area. The repaint() method of the Component class is then used to repaint the area updated as the
result of the mouse drag. This version of the repaint() method takes as its parameters the x,y
coordinate of the upper-left corner of the area to be redrawn and the width and height of this area.
Line drawing is not restricted in the same manner as oval and rectangle drawing. If it were, you would
not be able to draw lines that go up and to the right or down and to the left. The else part of the if
statement updates the starting position of the area to be repainted as the upper-leftmost point of the line
being redrawn. It then updates the ending position of the area to be repainted as the lower-rightmost
point of the line. The canvas is then repainted using the starting coordinates and the updated width and
height of the repaint area.
To get a better feel for the process of local screen repainting, try experimenting with the way the
repaint() method is used to update the canvas display.

- 247



TwoPointObject

The TwoPointObject class is used to keep track of the objects drawn by the user. It records the type
of object and its starting and ending coordinates. It also draws the objects on a Graphics object
passed as a parameter.
TwoPointObject defines the LINE, OVAL, and RECTANGLE constants, which are also used by the
MyCanvas class. The type variable is used to record the type of object being drawn. The startX,
startY, endX, and endY variables identify the starting and ending coordinates of the object.
Three TwoPointObject constructors are declared. The first constructor takes as its parameters the
type of object being drawn and its starting and ending coordinates. The second constructor leaves out
the ending coordinate and sets them to be the same as the starting coordinate. The last constructor
takes no parameters and creates a line at the coordinate 0,0.
The draw() method checks the type variable to determine which type of object is to be drawn. If the
object is a line, it uses the drawLine() method of the Graphics class to draw a line from its starting
to ending coordinate. If the object is an oval or a line, the w and l variables are assigned the width and
length of the object to be drawn. The drawOval() and drawRect() methods are used to draw an
oval or rectangle, respectively.

Drawing Text

The Font class of java.awt provides a platform-independent method of specifying and using fonts.
The Font class constructor creates Font objects using the font's name, style (PLAIN, BOLD, ITALIC,
or BOLD + ITALIC), and point size. Java's fonts are named in a platform-independent manner and
then mapped to local fonts that are supported by the operating system on which it executes. The
getName() method returns the logical Java font name of a particular font, and the getFamily()
method returns the operating system-specific name of the font. You'll learn the name of the standard
Java fonts in the next programming example of this chapter.
The FontMetrics class is used to return the specific parameters for a particular Font object. An
object of this class is created using the getFontMetrics() methods supported by the Componentclass and other classes, such as

the Graphics class. The FontMetrics class provides access to the
details of the implementation of a Font object.
When text characters are displayed, they are displayed relative to a baseline. The baseline is the line
drawn through the bottom of nondescending characters. For example, if you drew a line at the bottom of
most text displayed on this line, you would get the text's baseline. Some characters, such as g and y,
descend below the baseline. The number of pixels that the characters of a font descend below the
baseline is known as the font's descent. The number of pixels that the characters of a font extend above
the baseline is known as the font's ascent.


Figure 14.5: Font parameters.
In addition to a font's ascent and descent, a third parameter, referred to as the font's leading, is used to
describe the amount of vertical spacing, in pixels, used between the descent of a line of text and the
ascent of the line of text below it. The overall height of a font is the sum of its leading, ascent, and
descent, and is equal to the distance between baselines (in pixels) of vertically adjacent lines of text.
The getLeading(), getAscent(), getDescent(), and getHeight() methods of the
FontMetrics class are used to access these important font-related parameters. Figure 14.5 provides
a graphical description of these parameters.
The getMaxAdvance(), getMaxAscent(), and getMaxDescent() methods are provided for
backward-compatibility with earlier Java versions.

The FontApp Program

The FontApp program illustrates the use of the Font and FontMetrics classes and shows how to
draw text on a Graphics object. Its source code is shown in Listing 14.2.

FontappListing 14.2: The Source Code of the Program

- 248



import java.awt.*;
import java.awt.event.*;

public class FontApp extends Frame {
int screenWidth = 400;
int screenHeight = 400;
Font defaultFont;
// Declare & create FontCanvas object
FontCanvas fontCanvas = new FontCanvas();
String fontNames[];
int fontIndex = 0;
public static void main(String[] args) {

FontApp app = new FontApp()
;
}
public FontApp()
{


super("FontApp")
;
setupFontNames()
;
Button nextButton = new Button("Next Font")
;
nextButton.addActionListener(new ButtonHandler())
;
Panel panel = new Panel()
;
panel.add(nextButton)
;
add("North",panel)
;
add("Center",fontCanvas)
;
addWindowListener(new WindowEventHandler())
;
pack()
;
setSize(screenWidth,screenHeight)
;
show()
;


}


void setupFontNames()
{
// Get font names from local graphics environment
GraphicsEnvironment ge
=


- 249



GraphicsEnvironment.getLocalGraphicsEnvironment();

fontNames = ge.getAvailableFontFamilyNames();
}
class ButtonHandler implements ActionListener {

public void actionPerformed(ActionEvent ev){
// Switch fonts
int numFonts = fontNames.length;
if(numFonts > 1) fontIndex = (fontIndex + 1) % numFonts;
fontCanvas.repaint();

}
}
class WindowEventHandler extends WindowAdapter{

public void windowClosing(WindowEvent e) {
System.exit(0);

}
}
class FontCanvas extends Canvas {

// Extend Canvas to display fonts

public int displayFontName(Graphics g) {
String text = fontNames[fontIndex];
if(defaultFont == null) defaultFont = getFont();
FontMetrics fm = g.getFontMetrics(defaultFont);
int x = (screenWidth - fm.stringWidth(text))/2;
int y = 10 + fm.getLeading()+fm.getAscent();
g.setFont(defaultFont);
g.drawString(text,x,y);
return y+fm.getHeight();

}

public void paint(Graphics g) {
// Display U.S. alphabet
String text = "abcdefghijklmnopqrstuvwxyz";

- 250



int sizes[] = {12,14,18,24}
;
int y = displayFontName(g)
;
for(int i=0;i{


Font currentFont =

new Font(fontNames[fontIndex],Font.PLAIN,sizes[i]);
g.setFont(currentFont);
FontMetrics fm = g.getFontMetrics(currentFont);
int x = (screenWidth - fm.stringWidth(text))/2;
g.drawString(text,x,y+fm.getLeading()+fm.getAscent());
y += fm.getHeight();

}
}
}

}
The FontApp program enables you to display a sample of the fonts that are available on your system.
Figure 14.6 shows a possible display output. The program displays the name of a font and then a
sample of how the font renders the lowercase letters a-z in 12, 14, 18, and 24 point sizes. Click the Next
Font button and the next font supported by your system is displayed.
The FontApp class declares a number of field variables. The defaultFont variable identifies the
default font used by the program. The fontNames[] array is used to store the names of the fonts that
are accessible to Java.
The setupFonts() method obtains the local GraphicsEnvironment object using the static
getLocalGraphicsEnvironment() method of the GraphicsEnvironment class. It then uses the
getAvailableFontFamilyNames() method to obtain the names of all the fonts supported by the
system.
The paint() method of the FontCanvas class is where the primary processing of interest takes
place. It invokes the displayFontName() method to display the name of the next font to be
displayed. The displayFontName() method returns the vertical offset where the next text line should
be displayed. The paint() method uses a for statement to loop through the sizes array and display
a line at each point size. Note how the getLeading(), getAscent(), and getHeight() methods
are used to determine the vertical position of the text.

- 251



Figure 14.6: The FontApp program's output.

Displaying Bitmapped Images

The drawImage() method of the Graphics class is used to display bitmapped images. It has a
number of forms that take various arguments. In its simplest form, it takes as its arguments an object of
the Image class, an object that implements the ImageObserver interface, the x,y-coordinate where
the image is to be displayed.
The Image class is an abstract class that provides format-independent access to graphical images.
Image objects are created by invoking methods of other classes that create images. Examples of these
image-creating methods are the createImage() methods of the Component and Toolkit classes
and the getImage() methods of the Toolkit and Applet classes. The getImage() methods are
best methods for retrieving an image that is stored in a disk file or at a URL. Java currently supports
GIF- and JPEG-formatted images through these methods.
The ImageObserver interface is defined in the java.awt.image package. This interface provides a
set of constants and methods that support the creation and loading of images. The Component class
implements the ImageObserver interface; and in most cases, the ImageObserver object used as the
parameter to the drawImage() method can be supplied using the this identifier to reference the
current Canvas or Frame object being painted.

The ImageAppProgram

The ImageApp program shows how bitmapped images can be drawn in a program window using the
drawImage() method of the Graphics class. Its source code is shown in Listing 14.3.

ImageappListing 14.3: The Program

import java.awt.*;
import java.awt.event.*;

public class ImageApp extends Frame {
Image image;
public static void main(String[] args) {

ImageApp app = new ImageApp();
}
public ImageApp() {

super("ImageApp");

- 252



setBackground(Color.white)
;
// Use Toolkit to load image file
Toolkit toolkit = Toolkit.getDefaultToolkit()
;
image = toolkit.getImage("test.gif")
;
addWindowListener(new WindowEventHandler())
;
pack()
;
setSize(400,400)
;
show()
;


}
public void paint(Graphics g)
{


g.drawImage(image,0,0,this)
;
}
class WindowEventHandler extends WindowAdapter{


public void windowClosing(WindowEvent e) {
System.exit(0);
}
}

}
Before running the ImageApp program, copy the test.gif image from the \jc2\ch14 directory of
the CD-ROM to your jc2\ch07 directory. The ImageApp program displays the image in the test.gif
file.

When you run the ImageApp program, it will display the bitmapped image shown in Figure 14.7.
Figure 14.7: The ImageApp program.

- 253



The functionality of the ImageApp program isn't all that astounding. Its purpose is to illustrate the use of
the methods involved in loading and displaying image files. You can easily upgrade the program to
display arbitrary GIF or JPEG files by passing the image file name as a program argument.
The setBackground() method of the Component class sets the program background to white. The
getImage() method of the Toolkit class is used to load the image in the test.gif file and assign
it to the image variable.
The paint() method draws the image referenced by the image variable on the default Graphicsobject of the program window. It

accomplishes this using the drawImage() method of the Graphicsclass. The arguments to drawImage() include the image to be

displayed, the x,y coordinate where the
image is to be drawn, and the object implementing the ImageObserver interface associated with the
image. The this identifier is used to indicate that the program window is the ImageObserver.

Clipping

The AWT supports a painting feature known as clipping. Clipping enables you to restrict painting (or
drawing) operations to a particular shape. The Shape interface is implemented by classes that define
geometric shapes, such as Rectangle and Polygon. The setClip() method of the Graphics class
is used to specify a clipping region. It takes a Shape object as an argument. (Another version of the
setClip() method takes x, y, width, and height arguments.) When a clipping region is specified,
painting of a Graphics object is limited to the clipping region. The ClipApp program of Listing 14.4
shows how clipping works. This program creates a Rectangle object that is set as the clipping area. It
is located at (100,100) and is 200 pixels wide and high. Figure 14.8 shows the image displayed as the
result of clipping.

Note Clipping and Repainting When the AWT background thread invokes the

paint() methods of GUI objects to support repainting, it sets the clipping region

to the limited area of the applet or application window that requires repainting.

This speeds up the repaint operation and conserves processing resources.


Figure 14.8: The ClipApp program limits the painting area.

Listing 14.4: The Clipapp Program


import java.awt.*;
import java.awt.event.*;

public class ClipApp extends Frame {
Image image;
public static void main(String[] args) {

ClipApp app = new ClipApp();

- 254



}

public ClipApp() {
super("ClipApp");
setBackground(Color.white);
Toolkit toolkit = Toolkit.getDefaultToolkit();
image = toolkit.getImage("test.gif");
addWindowListener(new WindowEventHandler());
pack();
setSize(400,400);
show();

}

public void paint(Graphics g) {
// Set clipping region
g.setClip(new Rectangle(100,100,200,200));
g.drawImage(image,0,0,this);

}
class WindowEventHandler extends WindowAdapter{
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}

}
Chapter Summary

This chapter covered the classes and interfaces of java.awt that are used to implement drawing and
painting. You were introduced to the Canvas, Graphics, Image, and Font classes and learned how
they are used in conjunction with the paint() method. You also built several small Java applications
that provided concrete painting examples. You should now be prepared to test your knowledge of these
topics. The following review questions and exam questions will let you know how well you understand
this material and will give you an idea of how you'll do in related exam questions. They'll also indicate
which material you need to study further.

Key Terms

.. Painting
.. Repainting
.. Drawing
- 255



.
Clipping
Review Questions

1.
What is the relationship between the Canvas class and the Graphics class?
2.
Name three Component subclasses that support painting.
3.
What is the difference between the paint() and repaint() methods?
4.
What is the difference between the Font and FontMetrics classes?
5.
What is clipping?
6.
What is the relationship between clipping and repainting?
Exam Questions

1. Which of the following are passed as an argument to the paint() method?
A. A Canvas object
B. A Graphics object
C. An Image object
D. A Paint object
2.
Which of the following methods are invoked by the AWT to support paint and repaint
operations?
A.
paint()
B.
repaint()
C.
draw()
D.
redraw()
3.
Which of the following classes have a paint() method?
A.
Canvas
B.
Image
C.
Frame
D.
Graphics
4.
Which of the following are methods of the Graphics class?
A.
drawRect()
B.
drawImage()
C.
drawPoint()
D.
drawString()
5.
Which Font attributes are available through the FontMetrics class?
A. ascent
B. leading
C.
case
D. height
6.
Which of the following are valid forms of the drawImage() method of the Graphics
class?
A.
drawImage(Image image, int x, int y, ImageObserverobserver)
B.
drawImage(Image image)
C.
drawImage(Image image, int x, int y)
D.
drawImage()
7.
When the clipping region is set for a Graphics object, which of the following are true?
A.
Painting is restricted to the clipping region.
B.
Painting is excluded from the clipping region.
C.
All painting is prohibited.
D.
Painting takes place inside of and outside of the clipping region.
8.
Which of the following are true?
A.
The AWT automatically causes a window to be repainted when a portion of
a window has been minimized and then maximized.
B.
The AWT automatically causes a window to be repainted when a portion of
a window has been covered and then uncovered.
- 256



C.
The AWT automatically causes a window to be repainted when application
data is changed.
D.
The AWT does not support repainting operations.
Answers to Review Questions

1.
A Canvas object provides access to a Graphics object via its paint() method.
2.
The Canvas, Frame, Panel, and Applet classes support painting.
3.
The paint() method supports painting via a Graphics object. The repaint()
method is used to cause paint() to be invoked by the AWT painting thread.
4.
The FontMetrics class is used to define implementation-specific properties, such as
ascent and descent, of a Font object.
5.
Clipping is the process of confining paint operations to a limited area or shape.
6.
When a window is repainted by the AWT painting thread, it sets the clipping regions to
the area of the window that requires repainting.
Answers to Exam Questions

1.
B. The paint() method has a Graphics argument.
2.
A. The AWT causes the paint() method to be invoked.
3.
A and C. The Canvas and Frame classes inherit paint() from Component.
4.
A, B, and D. The Graphics class supports all the methods except drawPoint().
5.
A, B, and D. Ascent, leading, and height are available through FontMetrics.
6.
A. The first form is the simplest form of drawImage().
7.
A. The purpose of clipping is to restrict painting operations to the clipping region.
8.
A and B. The AWT automatically repaints portions of a window that require repainting as
the result of window movement and resizing operations.

No comments: