Wednesday, 13 May 2015

Abstract Window Toolkit (AWT)

The Abstract Window Toolkit (or Alternative Window Toolkit, depending on who you talk to) is a visual interface kit that comes with all the current implementations of Java. As its name indicates, though, the intent is for other-hopefully, more powerful and easier to use-toolkits to be developed by various vendors in the future. For now, if you want to do any interface work in Java, the AWT package is the way to go.

  

  These class structures might seem a bit intimidating at first, but if you glance through them, you'll see that most AWT classes just inherit from Object. In addition, all the interactive elements (except menus) inherit from Component. The only other very important thing to note is that because Applet inherits from Panel (which inherits from Container), applets can directly contain other objects such as buttons, canvases, and so on. This section describes how you can build hierarchies of containers in applets.

All the other classes are described as they become relevant in the following sections. Use the diagrams included in these sections as quick references when you want to find out what capabilities a class inherits. 

Graphics Class

The Graphics class is part of the AWT. It's contained in java.awt.Graphics, and it's the basic class for everything you'll draw on-screen. Applets have associated Graphics instances, as do various components such as buttons. Drawing methods, such as drawLine, work on a Graphics instance, so you'll see many calls in this form in a typical Java applet:
public void paint(Graphics g) {
    g.drawLine(10,10,20,20);
}
The Graphics class uses a standard computer coordinate system with the origin in the upper- left corner, as shown in Figure.


ll coordinate measurements in Java are done in pixels. The size of items, therefore, in absolute units such as inches or millimeters, differs on various machines due to differing pixels/inch values.
You'll find that whenever your program has to draw something, you'll be using Graphics class methods. The following sections discuss the most useful methods. Here's a listing of the methods that aren't covered later in this chapter, but that occasionally will be useful.
clipRect(int x, int y, int width, int height)
Changes the clipping region to the intersection of the current clipping rectangle and the one specified in the input arguments. This means that the clipping region can only get smaller.
copyArea(int x, int y, int width, int height, int new_x, int new_y)
Copies the rectangular area defined by x, y, width, and height to a rectangle defined by new_x, new_y, width, and height in the same Graphics object.
Graphics, create()
Makes a clone of the Graphics object.
Graphics, create(int x, int y, int width, int height)
Makes a clone of the Graphics object, but with a clipping region defined by the intersection of the current clipping rectangle and the one specified by x, y, width, and height. In addition, the origin of the Graphics object returned by this call is set to x,y.
setPaintMode()
Sets the painting mode to draw over; it is used to undo the effects of setXORMode.
setXORMode(Color a_color)
Sets the drawing mode to exclusive OR. The color is bitwise exclusive ORed with the current color and the foreground color to produce the final color.
translate(int x, int y)
Translates the origin of the Graphics area to the specified point.

The update, paint, and repaint Methods

You'll encounter three key methods over and over again as you work with the various user interface elements.
repaint
Requests a redraw of an item or an entire interface. It then calls update.
update
Controls what happens when repaint is called; you can override this method.
paint
Determines what's done when any item is redrawn. It's called whenever something needs to be redrawn-for example, when a window is uncovered. All displayable entities have paint methods that they inherit from Component.

Note
Interactive elements, such as buttons, are redrawn automatically; you don't have to implement a paint method for them.

All these methods are defined in the Component class. This means that all the various interactive controls and applets inherit these methods. Although all these methods can be overridden, you'll find that paint and update are the ones you work with most often. Listing 17.1 shows a simple example of how paint and repaint can be used.

Listing 17.1. An example of paint and repaint.
import java.awt.*;
import java.applet.Applet;


public class paint_methods extends Applet{
    int y;
    public void init() {
        y = 1;
    }
    public void start () {
        while(true) { 
            y += 1;
            repaint(); 
            //wait 50 milliseconds and then call repaint again
            try {
                Thread.sleep(50); 
                } catch(InterruptedException e) {}

        }
    }

    public void paint(Graphics g)
    {
        //draw a string to the screen
        g.drawString("Hello, World!", 25, y );
    }
}

After you run this code, you see the phrase Hello, World! slide down the screen. You're probably wondering why you don't see many copies of Hello, World! on-screen at the same time. The answer is the update method. Listing 17.2 shows the default update method.

Listing 17.2. The default update method.
public void update(Graphics g) {
    g.setColor(getBackground()); //set the drawing color to the
                                //background color
    g.fillRect(0,0,width,height); //fill the window with the
                                //background color
    g.setColor(getForeground()); //reset the foreground color
    paint(g); //call paint to redraw everything 
}

The first three lines erase whatever is in the Graphics object so that anything that was drawn before it is deleted. You can change this behavior by overriding the update method.

Listing 17.3. A revised update method.
public void update(Graphics g) {
    paint(g); //call paint to redraw everything 
}

One thing to remember about calling the repaint method is that it doesn't always execute immediately. Java repaints as soon as it can, but sometimes repaints pile up because the computer is busy. Remember that your applet might be running on some fairly slow platforms; in this case, Java throws out some of the repaints, discarding the oldest repaints first. Because of this practice, three other versions of repaint are available with different input parameters.
repaint(long time_in_milliseconds)
Tries to call update for the number of milliseconds specified in the input argument. If update can't be called by the end of the specified time, repaint gives up. Note that no error is thrown if the method gives up. You will want to use this version primarily for animations, when you know that repaints will occur frequently.
repaint(int x, int y, int width, int height)
Repaints only the rectangular part of the screen defined by x, y, width, and height.
repaint(long time, int x, int y, int width, int height)
Combines the previous two repaint versions so that only a portion of the screen is updated. If it can't be done before the specified time elapses (in milliseconds), it is skipped.
When you invoke repaint on a container, such as an applet, the AWT takes care of invoking update on all the items in the container-even ones inside other containers that are in the top-level container.

Working with Color

The AWT provides very generalized color support. The abstract ColorModel class enables you to define how colors are represented. The AWT comes with two predefined color models: IndexColorModel and DirectColorModel. IndexColorModel is used when images have a lookup table of colors and each pixel's value is an index in the lookup table. The pixel's color is determined by the color value in the lookup table specified by the index. DirectColorModel uses a 32-bit integer to hold the data for the color. Regardless of which color model you use, you still can represent individual colors as 32-bit integers (as described later in this section). In general, you won't have to worry about the ColorModel class.

RGB and HSB Color Formats

The AWT's normal color model is RGB; in this model, a color is defined by its red, green, and blue components. Each of these three values is an int with a value between 0 and 255. An RGB value can be stored in an int with bits 31 through 24 being unused, bits 23 through 16 for the red value, bits 15 through 8 storing the green value, and bits 0 through 7 for the blue component of the color. The applet in Listing 17.4 shows how to extract the color components from an int.

Listing 17.4. Extracting color components from an integer.
import java.awt.*;
import java.applet.Applet;


public class unpack_color extends Applet
{
    public void init()
    {
        //getRGB is a static method so you invoke it with the name of the 
        //class. You don't need a specific instance.

        int temp = Color.white.getRGB(); 
        unpack_colors(temp); 

    }
    public void unpack_colors(int the_color) 
    {
        int red, green, blue;
        //the highest order byte is unused
        //the next highest byte is red
        red = the_color & 0x00FF0000;
        //shift the value to the right so it's in the range 0-255
        red = red >> 16;
        //the next-to-last byte is green
        green = the_color & 0x0000FF00;
        //shift the value to the right so it's in the range 0-255
        green = green >> 8;
        //the lowest byte is blue
        blue = the_color & 0x000000FF;
        System.out.println("red = " + red + " green= " + green +
              " blue= " + blue);
    }
}

A Color class is available that enables you to use a single object rather than three ints to define a color. Most AWT methods that use colors require you to pass them an instance of a Color object.
The Color class also has several methods for manipulating and creating colors.

Note
All of the method descriptions in this chapter start with the type of value returned by the method (if no type is shown it's void) followed by the method name and its input arguments. For example,
means that the clipRect method does not return a value.
Graphics, create()
means that the create method returns a value of type Graphics.
Color, brighter()
Returns a new color that is approximately 1.5 times brighter than the current color.
Color, darker()
Returns a color about 70 percent as bright as the original color.
boolean, equals(Object item)
Checks to see whether two colors are the same.
int, getBlue()
Returns the blue component of a color.
Color, getColor(String color)
Returns an instance of the Color class given a string containing a decimal or hexadecimal number. For example, 0x0000FF produces a deep blue. This is a static method. This version and the next two versions are useful primarily when reading in parameters from HTML.
Color, getColor(String color, Color default)
Performs the same function as the preceding, except if the string isn't in the right format, it returns the color defined by the second parameter.
Color, getColor(String color, int rgb)
Performs the same function as the preceding, except you supply a default packed integer with RGB values, not an instance of color.
Color, getHSBColor(float hue, float saturation, float brightness)
Returns an instance of the Color class based on the supplied HSB values (hue, saturation, and brightness). This is a static method.
int, getGreen()
Returns the green component of the color.
int, HSBtoRGB(float hue, float saturation, float brightness)
Produces an integer containing the RGB values of a color-with blue in the lowest byte, green in the second byte, and red in the third byte-when given the three HSB values. This is a static method.
int, getRGB()
Returns the packed-integer version of the RGB values of a color.
int, getRed()
Returns the red component of a color.
float[], RGBtoHSB(int r, int g, int b)
Returns an array of floats containing the h, s, and b values of the equivalent color to the specified r, g, and b values.

Using HSB Colors

As you probably guessed from the names of some of these methods, the AWT also lets you work with the HSB model. In this model, colors are represented as hue, saturation, and brightness.
  • Hue: The hue-red or blue, for example-portion of the color. The value runs from 0 to 1/4 PI, with 0 corresponding to red and 1/4 PI to violet.
  • Saturation: Determines how far from gray a color is. The value runs from 0 to 1. A value of 0 corresponds to a gray scale. By varying this parameter, you can fade out a color picture.
  • Brightness: Determines how bright a given color is. The value runs from 0 to 1. A brightness of 0 gives you black. A value of 1 gives you the brightest color of the given hue and saturation possible.

There are a number of reasons to use the HSB representation. You can convert a color image to black and white by just setting the saturation of all the pixels to 0. Similarly, if you want to create a continuous color spectrum, it's easy to smoothly change the hue to get a continuum-within the limits of the color support of your monitor and Web browser-of colors.

Listing 17.5. Creating a rainbow.
import java.awt.*;
import java.applet.Applet;


public class rainbow extends Applet{
    int n_steps;
    int rainbow_width;

    public void init()
    {

    }
    public void paint(Graphics g)
    {
        float h,s,b;
        int x,y,i;
        Color temp_color; 
        int patch_width,patch_height; 
        float incr;

        n_steps = 256; 
        //define how much the Hue will change between steps
        incr = (float)(0.25*Math.PI/n_steps); 
        rainbow_width = 256;
        //figure out how wide each step would be
        patch_width = (int)(rainbow_width/n_steps);
        patch_height = 50;
        //fix the value of Saturation to the maximum value
        s = (float)1.0; 
        //fix the value of Brightness to the maximum value
        b = (float)1.0; 
        y = 40;
        x = 0;
        //draw a set of rectangles filled with the colors of
        //the rainbow 
        for(i=0;i<n_steps;i++) {
            h = incr*i;
            //create a new color using the HSB parameters
            temp_color = Color.getHSBColor(h,s,b);
            //set the current drawing color to the new color
            g.setColor(temp_color); 
            x += patch_width;
            //draw a rectangle whose upper lefthand corner is at
            //x,y and which is patch_width wide and patch_height
            //tall 
            g.fillRect(x,y,patch_width,patch_height); 
        }
    }
}

Geometric Classes

Several generally useful classes exist that are used to contain information about locations and shapes. They're used as arguments for many of the drawing-related methods.

Dimension

Stores a width and a height as attributes. You can access these attributes with this code:
Dimension d;
int w,h;
h = d.height;
w = d.width;

Point

Represents an x and y coordinate. The points x and y are accessible. Point also supports two methods.
move(int x, int y)
Sets the x and y values of the point to the input parameter values.
translate(int delta_x, int delta_y)
Adds the input parameter values to the current x and y values of the point-for example, x = x + delta_x.

Polygon

Represents an arbitrarily ordered list of vertices. You can directly access the three main attributes.
int x[]
Specifies the array of x values for the vertices.
int y[]
Specifies the array of y values. The nth y value and the nth x value define a vertex location.
Polygon has several useful methods.
int npoints
Specifies the number of vertices.
addPoint(int x, int y)
Adds a new vertex to the polygon.
Rectangle, getBoundingBox()
Returns the smallest rectangle that contains all the vertices.
boolean, inside(int x, int y)
Returns TRUE if the point defined by x and y is inside the polygon.

Rectangle

This has four public instance variables: the x and y coordinates of its upper-left corner (unless the height or width is negative, in which case the origin is in one of the other corners), its width, and its height. Rectangle has a number of methods that make working with rectangular regions easy.
add(int x, int y)
Adds the specified x,y point to a Rectangle by growing the rectangle to the smallest rectangle that contains the original rectangle and the point.
add(Point a_point)
Performs the same function as the preceding method, except the input parameter is a point rather than two integers.
add(Rectangle a_rectangle)
Grows the rectangle to the smallest one that contains the original rectangle and the rectangle supplied as the input parameter.
grow(int delta_w, int delta_h)
Grows the rectangle by the specified amount in height and width. Each side of the rectangle moves a distance delta_w so that the overall width of the rectangle increases by 2*delta_w. If the original rectangle width and height are 50,50 and the two input parameters to grow are 50,75, the new width and height would be 150,200.
boolean, inside(int x, int y)
Returns TRUE if the point x,y is inside the rectangle.
Rectangle, intersection(Rectangle rect)
Returns a rectangle that contains the intersection of the two rectangles. If the rectangles don't overlap, the resulting rectangle has 0 height and width.
boolean, intersects(Rectangle rect)
Returns TRUE if the rectangles overlap, including just a shared edge or vertex.
boolean, isEmpty()
Returns TRUE if the height or width of a rectangle is 0.
move(int x, int y)
Sets the origin of the rectangle to x,y.
reshape(int x, int y, int width, int height)
Sets the origin of the rectangle to x,y, its width to width, and its height to height.
resize(int width, int height)
Sets the width of the rectangle to width and its height to height.
translate(int d_x, int d_y)
Moves the rectangle a distance d_x in x and d_y in y.
Rectangle, union(Rectangle rect)
Returns a new rectangle that is the smallest one that contains both rectangles.

The Toolkit

This abstract class serves as a bridge between the platform-specific and the platform-independent parts of Java. It's the interface used to create peers for components such as buttons, and its methods let Java programs find out about platform-specific features such as the available fonts and the characteristics of the desktop. Because this is an abstract class, you don't instantiate it, but it does have a number of useful methods, including the following.
The Toolkit is your primary interface to machine-dependent information and interfaces. It's usable in applications and applets. Methods that are implemented by the Applet class, such as getImage, are available in applications via the Toolkit. You can use the static method getDefaultToolkit() to get the Toolkit, as in this snippet:
try {
    Toolkit current_toolkit = Toolkit.getDefaultToolkit(); 
} catch(AWTError e) {}

Note
The peer of a component is the platform-specific interface definition of the methods that the component has to support. Implementing a Java component on a new platform (Linux, for example) consists of writing native methods to fill in the peer interface definition.

Dimension: getScreenSize()
Returns the screen size in pixels.
int: getScreenResolution()
Returns the screen resolution in pixels/inch.
ColorModel: getColorModel()
Returns the ColorModel, which defines how color is represented on the platform.
String[]: getFontList()
Gets a list of the names of the fonts available on the platform.
FontMetrics: getFontMetrics(Font font)
Returns the FontMetrics, which provide measurements of a font's screen size, for the specified font on the desktop.
Image: getImage(String filename)
Gets an image from the file specified in the input argument.
Image: getImage(URL a_url)
Gets an image from a specified URL.
boolean, prepareImage(Image an_image, int width, int height, ImageObserver obs)
Forces the loading of an image, with a given width and height. You can use the image observer to monitor the progress of loading the image. If width and height aren't the current dimensions of the image, the image is scaled.
int, checkImage(Image an_image, int width, int height, ImageObserver obs)
Returns an integer that can be tested to determine the status of the image. ImageObserver constants that you can AND with the returned value are WIDTH, HEIGHT, PROPERTIES, SOMEBITS, FRAMEBITS, and ALLBITS. If the returned value ANDed with ALLBITS returns TRUE, the image is fully loaded.
Image: createImage(ImageProducer an_image_source)

Takes an image source, such as a filter, and creates an image.  

1 comment: