Chapter 13. Beginning AWTby Geoff Friesen In this chapter
|
What Is the AWT?
The
AWT
is a windowing framework that abstracts
Perhaps the best way to start learning the AWT is to take a brief look at those Java packages that comprise this framework. Table 13.1
Table 13.1. Java's AWT Packages
The AWT packages contain nearly 300 classes and interfaces, which is a solid foundation on which to build. In fact, other JFC APIs ”Swing, Accessibility, Java 2D, and Drag and Drop ”are built on the AWT.
Because Java 2D and Drag and Drop are closely
|
Graphics
One of the most enticing aspects of a computer is its capability to render graphical content. Right now, you're probably
The Fundamentals of Drawing
In the last chapter, you learned that JFC applets (or just applets for short) are assigned rectangular display areas in which to draw their output. These display areas (also known as
drawing surfaces
) are implemented as objects created from subclasses of the AWT's abstract
Component
class. Although
Component
will not be discussed until the
Note Applications can also use drawing surfaces. However, because applications do not default to using these surfaces, you must explicitly create an application with a drawing surface in mind. Such applications are known as JFC applications. You will learn how to create JFC applications in later chapters. Each drawing surface consists of small colored dots called picture elements ( pixels ) or points. The exact number of pixels on a drawing surface is controlled by that surface's width and height.
Tip
The
Component
class provides a
getSize
method that returns an object created from the
Dimension
class. This class contains two public field
A drawing surface is mapped out with a two-dimensional coordinate system that
The horizontal distance from the origin is known as an
x-coordinate,
whereas the vertical distance from the same origin is known as a
y-coordinate.
The x-coordinate increases through positive values from left to right, whereas the y-coordinate
Pixels are written out using the ( x, y ) format: x identifies the x-coordinate and y identifies the y-coordinate. The origin is written out as ( 0, ). Figure 13.1 illustrates the AWT's coordinate system. Figure 13.1. The AWT's coordinate system locates each pixel on a drawing surface.
A drawing surface is associated with an object that represents either a physical device (such as a video display or a printer) or a virtual device (such as an image memory buffer), and is capable of manipulating the appearance of this device's surface through a variety of method calls. This object is known as a
graphics context.
In essence, drawing on a drawing surface takes place by having the drawing surface object call graphics context
Graphics contexts are created by the AWT from subclasses of its abstract Graphics class. This class is located in the java.awt package.
The AWT uses a callback mechanism to handle drawing. Whenever a drawing surface must be updated, the AWT's drawing thread calls the drawing surface's
paint
method (either dir ectly or indirectly) and
In the previous chapter, you were
public void paint (Graphics g)
{
g.drawString ("Hello World!", 10, 30);
}
In this example, the AWT calls the paint method to update the drawing surface. In response, paint calls the drawString method, via Graphics argument g, to draw the string Hello World! 10 pixels from the left-hand side and 30 pixels from the top of the drawing surface.
Caution
The y-coordinate passed to
drawString
represents the location of an imaginary line on which the drawn
Drawing Text
Normally, when it comes to drawing graphics, the first thing many people want to draw is
text
(characters organized into meaningful groups ”such as words and sentences). A Java program can store text in
byte
arrays,
char
arrays, or
String
objects. These data structures contain only the 7-bit ASCII numbers (
byte
arrays) or 16-bit Unicode numbers (
char
arrays or
String
objects) that are associated with these characters. When text is displayed, these numbers are used in partnership with a graphics context's current font and color attributes to provide the text's "look." (Font and
Graphics
provides several methods for drawing text. Each method takes advantage of an imaginary line on which the text rests. This line is known as a
baseline.
Although most characters "sit" on this baseline, the bottom
The drawBytes method draws text from all or part of an array of bytes. This method has the following signature: void drawBytes (byte [] text, int offset, int length, int x, int y) Specifically, the text contained in the byte array is drawn using the graphics context's current font and color. The first text character is located at text [offset] and the number of text characters is specified by length. The leftmost text character is located x pixels from the left edge of the drawing surface. The baseline of these text characters is located y pixels from the top edge of the drawing surface.
Tip The capability to draw text from an array of bytes is useful when displaying files of information created by legacy programs. (Legacy programs typically use ASCII to store text.) When drawBytes is used to display this text, no conversion from ASCII to Unicode is required, which results in a performance boost. The drawChars method draws text from all or part of an array of characters. This method has the following signature: void drawChars (char [] text, int offset, int length, int x, int y) The text contained in the char array is drawn using the graphics context's current font and color. The first text character is located at text [offset] and the number of text characters is specified by length. The leftmost text character is located x pixels from the left edge of the drawing surface. The baseline of these text characters is located y pixels from the top edge of the drawing surface. Finally, the drawString method draws text from a String object. This method has the following signature: void drawString (String text, int x, int y) The text is drawn using the graphics context's current font and color. The leftmost text character is located x pixels from the left edge of the drawing surface. The baseline of these text characters is located y pixels from the top edge of the drawing surface.
Listing 13.1
Listing 13.1 The DrawTextDemo Applet Source Code
// DrawTextDemo.java
import java.awt.*;
import java.applet.Applet;
public class DrawTextDemo extends Applet
{
public void paint (Graphics g)
{
byte [] barray = { 0x41, 0x42, 0x43 } ;
char [] carray = { 'x', 'y', 'z'} ;
String s = "Even more text!";
g.drawBytes (barray, 0, barray.length, 10, 30);
g.drawChars (carray, 0, carray.length, 10, 60);
g.drawString (s, 10, 90);
}
}
Note Please refer to the previous chapter to learn how to execute an applet. The DrawTextDemo applet displays all text contained in barray, carray, and s on its drawing surface. The default font and color of graphics context g controls the appearance of this text.
The y-coordinate of each baseline ”30, 60, and 90 ”is
Figure 13.2. The DrawTextDemo applet shows text displayed using a graphics context's text drawing methods.
Caution Be careful when choosing the starting array index and length passed to either drawBytes or drawChars. Each method adds the length to the starting array index. If this sum is negative or equals/exceeds the length of the array, either an ArrayIndexOutOfBounds Exception object or a StringIndexOutOfBoundsException object will be thrown. (The same exceptions are thrown if the starting array index is negative or equals/exceeds the array's length.)
Drawing
|
| Member | Description |
|---|---|
| x | This int field specifies the point's x-coordinate. |
| y | This int field specifies the point's y-coordinate. |
| Point () | Initializes a Point object to (0, 0). |
| Point (int x, int y) | Initializes a Point object to ( x, y ). |
| Point (Point p) | Initializes a Point object to the contents of p. |
| equals (Object o) | Compares the current Point object with o (which must be a Point ) for equality. A Boolean true value is returned if they are equal. |
| getLocation () | Returns a copy of the current Point object. |
| move (int x, int y) | Moves the x-coordinate to x and the y-coordinate to y. |
| setLocation (int x, int y) | This method is identical to move. |
| setLocation (Point p) | Sets the current Point object to the contents of p. |
| toString () | Returns a String object containing a representation of the current Point object. |
| translate (int dx, int dy) | Translates the coordinates of the current Point object by adding dx to the x-coordinate and dy to the y-coordinate. |
The Dimension class (located in the java.awt package) encapsulates the width and height dimensions of a shape.
Table 13.3 presents Dimension 's fields and methods (except for a handful of overridden Java 2D methods) that are publicly accessible.
| Member | Description |
|---|---|
| width | This int field specifies the shape's width dimension. |
| height | This int field specifies the shape's height dimension. |
| Dimension () | Initializes a Dimension object to a height and width of zero. |
| Dimension (Dimension d) | Initializes a Dimension object to the contents of d. |
| Dimension (int w, int h) | Initializes a Dimension object to a width of w and a height of h. |
| equals (Object o) | Compares the current Dimension object with o (which must be a Dimension ) for equality. A Boolean true value is returned if they are equal. |
| getSize () | Returns a copy of the current Dimension object. |
| setSize (Dimension d) |
Sets the
|
| setSize (int w, int h) | Sets the size of the current Dimension object to a width of w and a height of h. |
| toString () | Returns a String object containing a representation of the current Dimension object. |
The Rectangle class (located in the java.awt package) encapsulates the coordinates and dimensions of a rectangular shape.
Table 13.4 presents Rectangle 's fields and methods (except for a handful of overridden and implemented Java 2D methods) that are publicly accessible.
| Member | Description |
|---|---|
| x | This int field specifies the shape's upper-left corner x-coordinate. |
| y | This int field specifies the shape's upper-left corner y-coordinate. |
| width | This int field specifies the shape's width dimension. |
| height | This int field specifies the shape's height dimension. |
| Rectangle () | Initializes a Rectangle object to an upper-left corner at (0, 0), a width of zero, and a height of zero. |
| Rectangle (Dimension d) | Initializes a Rectangle object to an upper-left corner at (0, 0) and a width/height specified by the contents of d. |
| Rectangle (int w, int h) | Initializes a Rectangle object to an upper-left corner at (0, 0), a width of w and a height of h. |
| Rectangle (int x, int y, int w, int h) | Initializes a Rectangle object to an upper-left corner at ( x, y ), a width of w and a height of h. |
| Rectangle (Point p) | Initializes a Rectangle object to an upper-left corner specified by the contents of p, a width of zero, and a height of zero. |
| Rectangle (Point p, Dimension d) | Initializes a Rectangle object to an upper-left corner specified by the contents of p and a width/height specified by the contents of d. |
| Rectangle (Rectangle r) | Initializes a Rectangle object to the contents of r. |
| add (int x, int y) | Adds the point specified by ( x, y ) to the current Rectangle object. The resulting rectangle is the smallest rectangle containing the original rectangle and point. |
| add (Point p) | Adds the point specified by p to the current Rectangle object. The resulting rectangle is the smallest rectangle containing the original rectangle and point. |
| add (Rectangle r) | Adds the rectangle specified by r to the current Rectangle object. The resulting rectangle is the union of the two rectangles. |
| contains (int x, int y) | Returns a Boolean true value if the point specified by ( x, y ) lies inside the boundaries of the current Rectangle object. |
| contains (int x, int y, int w, int h) | Returns a Boolean true value if the rectangle specified by ( x, y ), width w, and height h lies inside the boundaries of the current Rectangle object. |
| contains (Point p) | Returns a Boolean true value if the point specified by p lies inside the boundaries of the current Rectangle object. |
| contains (Rectangle r) | Returns a Boolean true value if the rectangle specified by r lies inside the boundaries of the current Rectangle object. |
| equals (Object o) | Compares the current Rectangle object with o (which must be a Rectangle ) for equality. A Boolean true value is returned if they are equal. |
| getBounds () | Returns a copy of the current Rectangle object. |
| getDimension () | Returns a Dimension object containing the width and height of the current Rectangle object. |
| getLocation () | Returns a Point object containing the upper-left corner coordinates of the current Rectangle object. |
| grow (int h, int v) |
Grows the current
Rectangle
object by
h
units on both the left and right sides and
v
units on both the top and bottom. The new upper-left corner is located at (
x - h,
y - v
), the new
width
is
2 * h
plus the old
width,
and the new
height
is
2 * v
plus the old
height.
If negative values are supplied for
h
and
v,
the rectangle shrinks
|
| intersection (Rectangle r) | Returns a new Rectangle object that contains the intersection of the current Rectangle object with r. |
| intersects (Rectangle r) | Returns a Boolean true value if the current Rectangle object and r intersect. |
| setBounds (int x, int y, int w, int h) | Sets the bounds of the current Rectangle object to x, y, w, and h. |
| setBounds (Rectangle r) | Sets the bounds of the current Rectangle object to the contents of r. |
| setLocation (int x, int y) | Sets the location of the current Rectangle object's upper-left corner to the location specified by ( x, y ). |
| setLocation (Point p) | Sets the location of the current Rectangle object's upper-left corner to the contents of p. |
| setSize (Dimension d) | Sets the size of the current Rectangle object to the width and height specified by d. |
| setSize (int w, int h) | Sets the size of the current Rectangle object to the width specified by w and height specified by h. |
| toString () | Returns a String object containing a representation of the current Rectangle object. |
| translate (int dx, int dy) | Translates the coordinates of the current Rectangle object by adding dx to the x-coordinate and dy to the y-coordinate of its upper-left corner. |
| union (Rectangle r) | Returns a new Rectangle object that contains the union of the current Rectangle object with r. |
The Polygon class (located in the java.awt package) encapsulates two arrays of point coordinates that connect the line segments comprising a polygon.
Table 13.5 presents those fields and methods (except for a handful of implemented Java 2D Shape methods) that are publicly accessible.
| Member | Description |
|---|---|
| npoints | This int field specifies the number of elements in both the xpoints and ypoints array. |
| xpoints | This int array field specifies the x-coordinate of each point making up this polygon. |
| ypoints | This int array field specifies the y-coordinate of each point making up this polygon. |
| Polygon () | Initializes an empty Polygon object. |
| Polygon (int [] xp, int [] yp, int n) | Initializes a Polygon object to n points where the x-coordinates are stored in the xp array and the y-coordinates are stored in the yp array. |
| addPoint (int x, int y) | Adds the point specified by ( x, y ) to the current Polygon object. |
| contains (int x, int y) | Returns a Boolean true value if the point specified by ( x, y ) lies inside the boundaries of the current Polygon object. |
| contains (Point p) | Returns a Boolean true value if the point specified by p lies inside the boundaries of the current Polygon object. |
| getBounds () | Returns a Rectangle object that contains the smallest rectangle parallel to the x and y axes and completely enclosing the polygon represented by the current Polygon object. |
| translate (int dx, int dy) | Translates the coordinates of each point making up the polygon by adding dx to the point's x-coordinate and dy to the point's y-coordinate. |
You've already seen some of Graphic 's polygon methods. However, there are two other methods specially designed for use with the Polygon class. These methods take a single Polygon argument, and have the following signatures:
void drawPolygon (Polygon) void fillPolygon (Polygon)
Listing 13.7 presents source code for the
DrawPolygonDemo2
applet that
// DrawPolygonDemo2.java
import java.awt.*;
import java.applet.Applet;
public class DrawPolygonDemo2 extends Applet
{
public void paint (Graphics g)
{
// Get the width and height of the applet's drawing surface.
int width = getSize ().width;
int height = getSize ().height;
int [] xp1 = { 30, 120, 70 } ;
int [] yp1 = { 90, 30, 110 } ;
Polygon p = new Polygon (xp1, yp1, xp1.length);
g.drawPolygon (p);
p = new Polygon ();
p.addPoint (90, 180);
p.addPoint (180, 120);
p.addPoint (130, 200);
g.drawPolygon (p);
int [] xp2 = { 130, 170, 150 } ;
int [] yp2 = { 50, 90, 120 } ;
g.fillPolygon (new Polygon (xp2, yp2, yp2.length));
}
}
The
Shape
interface provides methods that are used by objects representing geometric shapes. With the exception of
getBounds,
these methods are designed to be implemented by Java 2D shapes.
getBounds
returns a
Rectangle
object whose upper-left corner coordinates and dimensions completely enclose a shape. (You might have noticed that
Polygon
and
Rectangle
have a
getBounds
method. This is no
The
Graphics
class provides a number of utility methods for accomplishing
Clipping
Copying regions
Selecting drawing modes
Clipping is the technique of restricting graphics drawing to a specific region on a drawing surface. Usually, this region has a rectangular shape, although nonrectangular shapes are also possible (with Java 2D). Graphics provides several methods for defining and determining clipping regions. These methods include
clipRect
getClipBounds
setClip
getClip
The
clipRect
method
void clipRect (int x, int y, int width, int height)
The desired clip rectangle has an upper-left corner located at ( x, y ), and a lower-right corner located at ( x + width - 1, y + height - 1 ). However, if the current clip rectangle is smaller, the new clip rectangle will be the intersection of this rectangle and the desired clip rectangle. If no previous clip rectangle was established, the new clip rectangle will be the desired clip rectangle.
The getClipBounds method returns a Rectangle object containing the bounds of the current clip rectangle. This method has the following signature:
Rectangle getClipBounds ()
The setClip method sets the clipping region to the intersection of the current clipping region and its argument values. This method has the following signature:
void setClip (int x, int y, int width, int height)
The desired clip rectangle has an upper-left corner located at ( x, y ), and a lower-right corner located at ( x + width - 1, y + height - 1).
Graphics provides a variation of setClip that takes a single argument. This argument is an object whose class implements the Shape interface. The alternate setClip has the following signature:
void setClip (Shape clip)
The clipping region is restricted to that specified by clip. For non-Java 2D work, the object implementing Shape must be of type Rectangle.
The getClip method returns an object that implements the Shape interface and specifies the clipping region. This method has the following signature:
Shape getClip ()
Listing 13.8 presents source code to a ClipDemo applet that demonstrates clipping.
// ClipDemo.java
import java.awt.*;
import java.applet.Applet;
public class ClipDemo extends Applet
{
public void paint (Graphics g)
{
g.drawString (g.getClipBounds ().toString (), 10, 30);
g.clipRect (10, 40, getSize ().width 20, getSize ().height 80);
g.fillOval (0, 0, getSize ().width, getSize ().height);
String newClip = g.getClipBounds ().toString ();
g.setClip (0, 0, getSize ().width, getSize ().height);
g.drawString (newClip, 10, getSize ().height 10);
}
}
The ClipDemo applet displays a pair of text strings and a clipped oval. These strings represent the contents of Rectangle objects returned from calls to getClipBounds. In essence, they show the size of the clip region before and after a clip rectangle is established. Figure 13.11 shows Applet Viewer running ClipDemo.
Sometimes, you might want to copy a region of graphics from one area on the drawing surface and paste this copy to another area (perhaps for tiling or scrolling purposes). To simplify this task, Graphics provides the copyArea method. This method has the following signature:
void copyArea (int x, int y, int width, int height, int dx, int dy)
The region to be
Listing 13.9 presents source code to a CopyDemo applet that demonstrates copying regions.
// CopyDemo.java
import java.applet.*;
import java.awt.*;
public class CopyDemo extends Applet
{
public void paint (Graphics g)
{
g.fillArc (5, 15, 50, 75, 25, 165);
g.copyArea (5, 15, 50, 75, 50, 50);
}
}
The CopyDemo applet draws a solid arc and copies this region to another area on the drawing surface. Figure 13.12 shows CopyDemo running in the Applet Viewer.
Normally, when you draw a shape over a previously drawn shape, the new shape's pixels completely replace the old shape's pixels. This default drawing mode is known as paint mode. However, there is an alternate mode that you can use: XOR mode.
XOR mode dates back several
Nowadays, XOR mode is often used to draw the selection rectangle in painting programs. This rectangle (which is typically displayed with a dashed or
Graphics provides a pair of methods for switching to either paint mode or XOR mode:
setPaintMode
setXORMode
The setPaintMode method switches the drawing mode to paint mode. Because paint mode is the default drawing mode, you would only use this method to switch from XOR mode back to paint mode. This method has the following signature:
void setPaintMode ()
In contrast, the setXORMode method switches the drawing mode to XOR mode, and has the following signature:
void setXORMode (Color c)
Color argument c is known as an XOR color. This color is usually the drawing surface's background color, but it can be any color. For each subsequently drawn pixel, the XOR color will be XORed with the color of the pixel being overwritten and the graphics context's current color.
Listing 13.10 presents source code to an applet called ModeDemo that demonstrates paint and XOR modes.
// ModeDemo.java
import java.awt.*;
import java.applet.Applet;
public class ModeDemo extends Applet
{
public void paint (Graphics g)
{
int w = getSize ().width;
int h = getSize ().height;
int midW = w / 2;
g.drawString ("Use XOR", 0, 30);
g.drawOval (7, 37, 50, 50);
g.setXORMode (Color.white);
for (int i = 0; i < 15; i += 3)
{
g.drawOval (10 + i 3, 40 + i 3, 50, 50);
g.drawOval (10 + i, 40 + i, 50, 50);
}
g.setPaintMode ();
g.drawString ("No XOR", midW, 30);
g.drawOval (midW + 7, 37, 50, 50);
for (int i = 0; i < 15; i += 3)
{
g.drawOval (midW + 10 + i 3, 40 + i 3, 50, 50);
g.drawOval (midW + 10 + i, 40 + i, 50, 50);
}
}
}
When you run
ModeDemo,
you'll see the applet's drawing surface divided into two halves: Both