Previous Page TOC Next Page See Page



9


The Order Entry System: Adding Graphics and a Logo


by Michael Girdley

Currently, some of the most exciting aspects of Java are those dealing with graphics. This chapter covers these features. First, this chapter covers the AWT Graphics class, which allows you to implement many different graphical items. These features involve drawing, displaying images, and setting colors, among others. This chapter also discusses the Canvas class, which is a special type of component designed for use in dealing with graphics in AWT programs. The Order Entry system is also extended in this chapter as you include the concepts dealt with in this chapter in the applet.

The AWT Graphics Class


The AWT graphics class is an abstract class that is the basis for all graphical constructions in Java. You cannot implement this class directly. To utilize it, you must copy another instance of the Graphics class or have a component generate it. The Graphics class enables you to drawLines, implements boxes and 3-D boxes, uses different fonts, and implement different colors. A number of functions in the Graphics class implement these capabilities.

The paint and update Methods


You use the paint and update methods to implement the features in the Graphics class in your programs. You use the following code line to declare the paint method:

public void paint(Graphics g)  {

Note that the paint method accepts one parameter, an instance of the Graphics class. Here's what happens in the paint method: Your paint method is sent an instance of the Graphics class, which defines the current status of the segment of the display that your class is responsible for. Next, your paint method modifies that state using the methods in the Graphics class and those implemented in other classes. Then the Java runtime modifies the display to eventually match those changes once the execution of your paint method is completed. Then the whole process begins again. Understanding this process is key to writing your own paint method. The paint method is written to describe in code how the display area should look at the program's current status.

CAUTION:


One of the most important concepts about applying the graphical features of the AWT to your programs is that every time the paint method is executed, it does not imply that any changes in the display are immediately displayed. As you will see in later chapters on multithreading, the display of changes is sometimes less important than other processes that are running in parallel to your applet.

The update and paint methods are initially implemented in the Component class of the AWT. The paint declaration in the code of the Component class is empty until you override it. The update method, by default, resets many of the settings in the Graphics instance you are using and then calls the paint method. The times you override it include occasions on which you want to change the way your displays are changed or in dealing with canvases and animation.

To include the different primitives of the Graphics class, be sure to import it into your program:

import java.awt.Graphics;



You can implement the update and paint methods. However, you usually don't make any calls to them. There are instances in which you want to force a call to repaint a piece of display as soon as possible. This is discussed in the section covering the repaint method in this chapter, "The repaint Method."

The GExampleApplet example applet shown in Listing 9.1 demonstrates these ideas. The output from this applet is Figure 9.1.

Listing 9.1. The GExampleApplet code listing.

import java.awt.*;
import java.applet.*;
public class GExampleApplet extends Applet {
    public void paint(Graphics g)  {
        g.drawRect(10, 10, 100, 100);
    }
}

** 09wpj01.pcx **

Figure 9.1. The GExampleApplet when viewed through the Appletviewer utility.

In Listing 9.1, the applet life cycle control methods (init, stop, and so on) are all left as defaults. The default paint method is overridden, and the new method includes code to draw a rectangle on the applet panel using the drawRect method included in the Graphics class. The new paint method gets called repeatedly, and the same rectangle gets drawn on the screen. Complete coverage of the graphics primitives is a major focus of this chapter.

CAUTION:


This chapter does not cover every method available in the Graphics class. If you want a description and listing of all the methods available, check the source code: SRC/JAVA/AWT/Graphics.java. Or try the Java API included on the CD-ROM that accompanies this book.



Note that Java's coordinate system begins with 0,0 at the top left. So, the bottom-right corner of a screen segment of width and height 100 would be point (100,100).


The repaint Method


Sometimes you want to demand that the Java runtime repaint a component display as soon as possible. This is done through a call to the repaint method in the Component class.



Remember, since almost all the visible pieces of the AWT, including applets, panels, and frames, are descendants of the Component class, when I talk about painting components, I am not just talking about buttons and scrollbars, but containers too.

There are a number of other types of calls to the repaint method. For example, you can specify exactly how long you want it to be before the component is painted again. You can also specify what portion of the component display you want to be repainted (very helpful in animations). For now, just know that a call to the repaint() method of a component makes sure that the display is updated. Simply insert a repaint() call, and the display update will be expedited by the Java interpreter executing your code.

Java Graphics Primitives


The following sections cover the multiple methods available in the Graphics class and related classes that are used to draw graphics.

The drawString Method and Fonts


The process of drawing graphical strings is very simple using the AWT. It is also very versatile. You can specify the exact size, font characteristics, and placement of the strings that you draw onto your instance of Graphics class.

The first step in drawing a string on a component is to set the font specifics that you want. This is accomplished using the Font class, which is part of the AWT package. For example, include this code line to declare an instance of the Font class representing the Courier font with an italic style and a point size of 18:

Font afont = new Font("Courier", Font.ITALIC, 18);

The first parameter sets the font that you want to use. Examples of some of the available fonts are Helvetica, Courier, and TimesRoman.

CAUTION:


Not every font is available on every system. On some systems, for example, Helvetica is not available. When the font is not available, Java reverts to a default font, which is generally Courier. It is wise to take this factor into consideration when representing strings graphically since you can easily specify TimesRoman and end up with Courier on one machine and TimesRoman on another, both running the same Java code.

The second parameter of the Font constructor describes the font constants, which define italics, bold, and so on. These constants can be Font.ITALIC, Font.BOLD, or Font.PLAIN. You can also define a font to be both bold and italic by using the sum of the two constants. So, to set the font to be both bold and italic, send the second parameter in as Font.BOLD + Font.ITALIC. If you want the text to be plain, use the Font.PLAIN constant as your parameter.

And finally, the third parameter sets the point size of the font in pixels.

You must set the font you have constructed to be the current font for the instance of the Graphics class that controls the display you are going to add the string to. To do this, use the setFont method of the Graphics class. The following line sets the current font of an instance of the Graphics class called g equal to the font you just declared:

g.setFont(afont);

And finally, to draw the string, you use the following line:

g.drawString("Leopards Aquatics", 10, 20);

The drawString method accepts three parameters. The first parameter is a string representing the text you want to draw, and the second and third parameters describe the x and y pixel position of the string, respectively. The following short applet demonstrates the inclusion of these statements into a complete applet that draws the string onto the applet face. The code is shown in Listing 9.2, and the resulting display is shown as Figure 9.2.

Listing 9.2. The FirstDrawStringExample applet code.

import java.awt.*;
import java.applet.*;
public class FirstDrawStringExample extends Applet {
    private Font afont = new Font("Helvetica", Font.BOLD, 18);
    public void paint(Graphics g)  {
        g.setFont(afont);
        g.drawString("Leopards Aquatics", 10, 20);
    }
}

** 09wpj02.pcx **

Figure 9.2. The output from the FirstDrawStringExample when viewed from the Appletviewer utility.

In the FirstDrawStringExample, note that an instance of the Font class is first declared from the AWT package that handles the font business such as scaling and italicizing. Then, in the paint method, the font is set to be the current font for the g variable, which describes the data concerning the display area you are dealing with. Finally, the drawString method actually draws the sting at x equals 10 pixels and y equals 10 pixels from the origin.

Table 9.1 lists some of the Font methods that are available.

Table 9.1. Font methods.

Method Description String getName() Returns the name of the font (Helvetica, and so on) int getStyle() Returns the constant that is the style of the font boolean isPlain() true or false depending on whether the font is Font.PLAIN boolean isBold() true or false depending on whether the font is Font.BOLD boolean isItalic() true or false depending on whether the font is Font.ITALIC getFont() Returns an instance of the currently selected font

Defining Colors


Just as the Font class implements methods and values to define the different fonts and settings, the Color class in the AWT package implements the ability to manage color in your programs.

There are two ways to specify a color in Java. The first way is to specify the amount of the red, green, and blue components in the color. These values range from 0 to 255 for each different component. You should probably recognize this as the RGB color scheme. Java uses a 24-bit color specification, which is called True Color on some platforms. To create an instance of the Color class while initially setting the color in this manner, you can utilize the Color constructor, which accepts three different integers. For example, if you want to define a color to be slightly darker than pure white, you can use the following line:

Color AColor = new Color (240, 240, 240);

In this code line, you are setting the red, green, and blue. Red is first, green is second, and blue is third.



There is actually a third Color constructor. It takes three float parameters that range from 0.0 to 1.0. It is basically the same as the preceding constructor, except the range per value is now 0.0 to 1.0 instead of 0 to 255. Neither method is more accurate because the method utilizing floats (from 0.0 to 1.0) simply converts those values to integers and calls this first method that takes 0 to 255.

The second way to set a color is to use one of the colors defined in the Color class itself. For example, if you want to create white, you can use the following line:

Color WhiteColor = new Color(Color.white);

Table 9.2 shows a listing of the different color constants available in the Color class.

Table 9.2. The color constants available in the Color class.

Color.white Color.lightGray Color.darkGray Color.gray Color.red Color.pink Color.orange Color.yellow Color.green Color.magenta Color.cyan Color.blue

Two more methods, which can prove to be very useful, are available in the Color class. One brighter method returns a brighter version of the calling color. For instance, if you want to brighten a Color called AColor, you can use the following line:

AColor = AColor.brighten();

There is also a similar method called darken along with a number of less useful methods in the Color class. For more information on these methods, check the source code in the class library. However, it isn't likely you'll need more than is described here.

Setting and Using Colors


Once you define a Color, there are a number of ways to use it.

To set the current color that you want to draw with in your instance of the Graphics class, you can use the setColor method in your paint function. This method accepts an instance of the Color class and sets the current drawing color to that color. You can imagine this to be like changing drawing-pen colors. Once you select setColor, everything you draw until you set the color again is drawn in that color. The default color is black. The following line sets the current drawing color to pink:

g.setColor(new Color(Color.pink));

Besides setting the "pen" color, you can also set the foreground and background colors for a component. These two methods are setForeground and setBackground, respectively. Call this method for a component, and the color gets set to the value of the instance of the Color class, which is sent in as the parameter. Note that these two functions set the background and foreground for the entire component, including graphics that are already drawn. So, if you draw some graphics in black and then set the foreground color to green, the original black drawing turns green.

The MegaColorExample explores the color capabilities of the AWT and is shown in Listing 9.3. The output is shown in Figure 9.3.

Listing 9.3. The DrawStringExample applet code.

import java.awt.*;
import java.applet.*;
public class DrawStringExample extends Applet {
    private Font afont = new Font("Helvetica", Font.BOLD, 18);
    public void init() {
        setBackground(Color.black);
    }
    public void paint(Graphics g) {
        g.setColor(Color.green);
        g.setFont(afont);
        g.drawString("This is krazee!", 10, 40);
    }
}

** 09wpj03.pcx **

Figure 9.3. The output from the DrawStringExample applet.

In this applet, an instance of the Font class is declared and constructed. Then the init method takes care of initially setting the background color to black. And finally, the code in the paint method sets the current drawing color to be green. Then it sets the current font to be the afont variable and then draws the string on the applet panel itself.



You can also utilize the drawBytes and drawChars methods in the Graphics class. They have limited uses, but for more information on them, check java\src\java\awt\Graphics.java included with your JDK.


Precision String Alignment


In the preceding example applet, you had to guess where to place the string on the panel. For example, centering the string on the applet panel involves some serious measurement. But the AWT provides a class that automates and simplifies this process. This class is named FontMetrics and is incredibly useful in simplifying the process of placing graphical strings. It is highly useful in centering strings or animating strings. Table 9.3 summarizes the methods available in the FontMetrics class.

Table 9.3. FontMetrics methods available.

Method Description int stringWidth(String) Computes and returns the width of a string in pixels. int getAscent() Returns the number of pixels from the top of the uppercase characters to the original y. int getDescent() The opposite of the getAscent function. int getMaxAscent() The maximum ascent value of all the characters in the string. int getMaxDescent() The maximum descent value of all the characters in the string. int getHeight() This returns the total height (including ascent, descent, and so on) of the font.

These methods are straightforward. To use them, you need to declare an instance of the FontMetrics class in your applet. The following code segment declares an instance of the FontMetrics class and then sets it to return information about a font called AFont:

FontMetrics AFontMetrics = new FontMetrics(AFont);

The different methods listed are all yours for the calling. To find the total height of your font using the declared AFontMetrics class, use the following line:

AFontMetrics.getHeight();

CAUTION:


Remember that the FontMetrics class is part of the AWT package, so make sure to import it into your program.

When you place lines of graphical text one after another, increment by the getHeight() function of the Font you are using. To center a string, use this.size.height() and this.size.width() to find out how wide your component screen area is. Then compute where to place your string based on this information and the width of the string in pixels that you can get using the FontMetrics class.

Drawing


So far, this chapter has covered how to draw strings, do neat things with them, and set colors. The following sections cover the graphics primitives you expect in any toolkit. The java.awt.Graphics class includes methods for drawing lines, arcs, polygons, rectangles, and so on. These methods are included in the paint method of your programs.

drawLine

drawLine is the basic graphical primitive. It takes four parameters that are two (x, y) pairs. To draw a line from (0, 10) to (50, 50) on a Graphics g, you use the following line:

g.drawLine(0, 10, 50, 50);

The first two parameters are x1 and y1, respectively, and the final two parameters are x2 and y2.

drawPolygon

The implementation of this function is just an extension of the drawLine function. There are three parameters: the first two are integer arrays and the third is the number of points, n, in the polygon. The first array contains the x1 through xn, and the second contains y1 through yn. The declaration for the drawPolygon method in this graphics class takes this format:

void drawPolygon(int x[], int y[], int numprs)  {

There is also a second way to draw polygons. It involves declaring an instance of the Polygon class and then adding your points to the variable one at a time. The following code segment declares an instance of the Polygon class, adds three points, and then sends the polygon to be drawn:

Polygon PGon = new Polygon();
PGon.add(1,2);
PGon.add(4,4);
PGon.add(30,30);
DrawPolygon(PGon);

Both versions work and do the same job.

drawArc

drawArc is used to draw arcs. The arc drawn is specified by a bounding rectangle. It takes six parameters: the starting x and starting y, the width and height of the bounding rectangle, and the starting and finishing degree positions of the arc. drawArc takes the format

drawArc(int x, int y, int WidthofRect, int HeightofRect, int StartDeg, int EndDeg)  {

where x and y specify the center of the arc, WidthofRect and HeightofRect specify one corner of the bounding rectangle of the arc, and the remaining two parameters specify the beginning and ending degree positions of the arc. A summary of the drawing primitives is shown in Table 9.4.

Table 9.4. The available drawing primitives.

Method Description drawRect(int x, int y, This draws a rectangle. It accepts four. int width, int height); Parameters: the initial x and initial y, and the width and height of the rectangle. drawOval(int x, int y, This draws an oval whose center is (x, y), int width, int height); and the width and height specify the distance from the origin to the side of the bounding rectangle and the top of the bounding rectangle respectively. drawRoundRect(int x, int x, This draws a rectangle with rounded int width, int height, corners. The parameters are the same as in arcWidth, int arcHeight); in the drawRect function except for the last two parameters. The arcWidth and arcHeight specify the bounding width and height for the curved corners. draw3DRect(int x,int y, This is the same as the drawRect method int width, int height, except it adds a Boolean field that boolean ThreeD); specifies that the box should be raised off of the panel if it is true. clearRect(int x, int y, Draws an outlined, clear rectangle using int width, int height) the current background color.

Filling


Filling is as simple as it gets: for all these methods described in the "Drawing" section, replace the word "draw" with the word "fill" and you're ready to go. For example, the following code draws a filled rectangle starting at 0,0 and of width 15 and height 30:

g.fillRect(0, 0, 15, 30);

Again, to draw these same shapes filled with the current color of the graphics, simply replace the word "draw" with "fill." This also works fine with 3-D rectangles.

AdrawingExample Applet


The AdrawingExample example in Listing 9.4 incorporates some of these methods into an applet that draws onto its main panel. The applet has a paint method, which draws three different figures using the primitives discussed. No action, no motion, so the values stay the same in the paint method. Of course, when the time comes for animation later in the book, the paint method is the place where the work gets done. But for now, the Java runtime calls paint over and over, and consistently draws the same image on the screen. The output from the applet is shown in Figure 9.4.

Listing 9.4. The ADrawingExample applet code.

import java.awt.*;
import java.applet.*;
public class ADrawingExample extends Applet {
    public void paint(Graphics g) {
        // Draw a rectangle starting at 10, 15 with a height of 100
        // and a width of 120.
        g.drawRect(10, 15, 100, 120);
        // Draw a 3D rectangle starting at 150,15 with a height of
        // 140 and a width of 100.
        // The arc width is 15 and the arc height is 10 for the corners.
        g.drawRoundRect(150, 15, 100, 140, 15, 10);
        // Draw a filled arc which is 75% filled: going from 0
        // degrees to 270 and a bounding rectangle of 130 in
        // width and 140 in height.
        g.fillArc(280, 35, 130, 140, 10, 280);
    }
}

** 09wpj04.pcx **

Figure 9.4. ADrawingExample demonstrates the basic method to use the different drawing primitives in the AWT's Graphics class.



Basically, the only tricky issue about using these methods is keeping your parameters straight. Two things can help you with this: One, have a reference such as this book handy to check your implementations. And two, print out the actual source code for the Graphics package and refer to it.


Displaying and Dealing with Images


Java allows different images to be imported and displayed. There are a great multitude of types of image formats in the world today, and a number of them are supported by Java.

The basic class for image storage is the Image class. The Image class is platform dependent. It is first implemented as abstract and then fully coded in the classes that define the platform-specific code. However, this isn't of concern to you since one of the principles of object-oriented design is that you aren't interested in how things get done, just that they do. You are guaranteed a certain specification in the Image and other library classes.

To declare an instance of the Image class use the following line:

Image AnImage;

You should notice that there is no constructor to set up an instance of the Image type. Instead, you go about placing pictures into the Image type through other methods while the construction is taken care of for you.

Getting Images


There are a couple of methods available to load images into your programs. The first method is specific to some components, and it involves using the getImage method and the getDocumentBase method to place the image into the instance of Image. The getImage function returns an instance of the Image class, which you then can set another instance equal to that value. The getDocumentBase returns the URL of the document that the applet is embedded in. You can use the getCodeBase function to return the position of your actual applet code if you want to place your images in the same location as your applet code.

The following line gets an image called Spalding.gif, which is found in the same directory as the applet class file:

AnImage = getImage(getDocumentBase(), "Spalding.gif");

This is simple enough. The first parameter is a function that defines the basis for where the image was found. It returns an instance of the URL class that defines an http address. The second, of course, is the name of the image itself.

The second method involves the direct use of the Toolkit class. The AWT Toolkit is used to bind with a platform-specific implementation of the toolkit. It provides different functions when using Images. This is a more specific manner to specify how you will get the image. To get an image using the toolkit, use the following declaration:

AnImage = Toolkit.getDefaultToolkit.getImage("Spalding.gif");

This statement accesses the default toolkit for a platform and then calls that toolkit's getImage function, which returns an instance of the Image class. This class is then placed in the AnImage variable. Note that the Toolkit is abstractly implemented in the AWT and then completely implemented in a local machine's platform-specific libraries.



There are a number of other implementations of the getImage method in both of these areas. For more information, check the source code in the class libraries. These implementations, however, should suit you fine for most tasks.

CAUTION:


You must use the toolkit to get images into your programs if you are creating an application. The first method is useful only with applets because Sun has incorporated the toolkit features into the applet class for simplicity.


Displaying Images


Displaying instances of the Image class after you have placed an image into them using one of the above methods is simple. You will utilize the drawImage function in the Graphic class to paint your image onto the display. The following code line tells a Graphics g to draw AnImage image you declared previously at coordinates (10,20):

g.drawImage(AnImage,  10, 20, this);

The first parameter is the image itself. The second and third parameters are integers that specify the x and y coordinates. And finally, the last one specifies an instance of ImageObserver, which sets what object receives notification of happenings during the loading and display process of the image. You learn more details about the Java Image model in the upcoming section, "The Java Model of Images." In this case, the this keyword refers to the object in which this code is contained.

The applet example ImageExample loads an image and then paints it onto the Applet panel, as shown in Listing 9.5. The output is shown in Figure 9.5.

Listing 9.5. The ImageExample applet code.

import java.awt.*;
import java.applet.*;
public class ImageExample extends Applet {
    private Image MyImage;
    public void init()  {
        // Load the image called Spalding.gif into the MyImage variable.
        MyImage = getImage(getDocumentBase(), "Spalding.gif");
    }
    public void paint(Graphics g) {
        // Paint the display with our image.
        g.drawImage(MyImage, 10, 20, this);
    }
 }

** 09wpj05.pcx **

Figure 9.5. The output from the ImageExample applet, which loads an image and displays it on the applet panel.

Table 9.5 summarizes the different implementation of the drawImage method.

Table 9.5. drawImage methods available.

drawImage(Image img, int x, int y, Image Observer iob) drawImage(Image img, int x, int y, int w, int h, ImageObserver iob) drawImage(Image img, int x, int y, Color bgcolor, ImageObserver iob) drawImage(Image img, int x, int y, Color bgcolor, int w, int h, ImageObserver iob) Variables x: The x coordinate where the image will be placed y: The y coordinate where the image will be placed bgcolor: The background color onto which the image will be drawn w: The allocated width for the image display h: The allocated height for the image display iob: An instance of the ImageObserver class (explained in the next section)

If you do not provide the exact space that your image occupies originally, it is scaled to fit. So, make sure that you provide the right dimensions. Otherwise, your images will likely be distorted by the scaling. The ImageObserver in this method is notified only if the graphic is incomplete.

The Java Model of Images


The Web presents a problem when dealing with images. There is a notable amount of time that your applet needs to wait for applets to download. You don't want a people browsing your pages to leave because they have to wait too long to see an image. Java is designed with this facet of networking in mind. The model of how its images are loaded is reflected in how it deals with images.



The model is based on interaction between three different pieces: the ImageProducer, the ImageObserver, and the ImageConsumer types. Image producers get images and then relate that image to the consumer. You don't need to worry about exactly where they are because this consumer and producer process happens out of your view for the most part. Image observers are objects that have a stake in what's going on. They can be interested in whether an image is loading or is incomplete.



For example, the this keyword included as a parameter in earlier declarations specified the current object to be an image observer. You commonly see an observer set to be the current object by using the this keyword. Using this keyword says that you want the current object to be notified if things are incomplete.



The process of handling these notifications is done through an ImageObserver interface included in applets and other containers. To find out exactly what has gone wrong, you access the returned flag to the interface and then compare that to the constants held in the ImageObserver class. This isn't really as important as it sounds, but if you are interested, check the library source code to implement it for yourself.

Some Killer Reserved Words


Here are some "killer" reserved words (by which, I mean powerful words) and their meanings:



finalize This says that you're finished with an instance of an object and you want the runtime to free the object's resources.



super A class' parent.



super() The constructor of a class' immediate parent.



this Refers to the current class.



The MediaTracker is a utility class that allows you to manage and track the loading of media components including Images. This class uses the concept of threading. Threading is covered in Chapter 16, "Multithreading with Java," and the class is described at that time.


A Final Component: Canvases


All the graphical examples so far have been drawn onto the applet panel. This has worked great, but Figure 9.6 shows what can happen if components and graphics are combined in this way on the same panel.

** 09wpj06.pcx **

Figure 9.6. The dangers of mixing components and graphics on the same panel.

Since you don't know where exactly each of your components will end up, it is impossible to be sure that the graphics and components don't conflict when your applet appears on different machines. What is the solution? Well, Java has a component that is designed to solve this problem: the Canvas class.

Canvases are components that are designed to be drawn upon just like an artist's canvas. You can draw onto a canvas and insert it into another container or your applet display itself. The Canvas class has its own paint() method, which handles what is drawn on the canvas face just as with the Applet and Frame classes. For this reason, Canvases must be declared as classes separate from the class that displays them.

Here are the steps to include a Canvas in your applet:

  1. 1. Inside your applet file, declare another class that extends the Canvas class.
  2. 2. Declare a public void paint(Graphics g) method in the new class from Step 1.
  3. 3. In the paint void from Step 2, do whatever drawing or image displaying you want to do onto the canvas.
  4. 4. If you want to tell the Canvas when to refresh immediately, have your other methods in the class from Step 1 call the repaint method when you want to do so.
  5. 5. Declare an instance of your new class in your applet and add it to your applet panel.

And then you're ready to go. The CanvasImageFiesta applet is shown in Listing 9.6. It puts these steps into practice. It also demonstrates the process of importing and displaying images in the canvas. The resulting output is shown in Figure 9.7.

Listing 9.6. The CanvasImageFiesta applet code.

import java.awt.*;
import java.applet.*;
public class CanvasImageFiesta extends Applet  {
    public void init ()  {
        // Typical button delcaration here.
        Button AButton = new Button("Ack!");
        add(AButton);
        Image anImage = getImage(getDocumentBase(), "Ian.gif");
        // Declare and setup the instance of the OurCanvas class
        OurCanvas OC = new OurCanvas(anImage);
        add(OC);
    }
}
class OurCanvas extends Canvas {
    private Image AnImage;
    OurCanvas (Image InImage) {
         // We have to set the size, otherwise it is invisible.
           resize(250,200);
         // Put the image into the AnImage variable.
         AnImage = InImage;
        }
          public void paint(Graphics g)
                {
            // Draw the image on our canvas.
                  g.drawImage(AnImage,5,5,this);
                }
}

** 09wpj07 **

Figure 9.7. The output from the CanvasImageFiesta, which demonstrates both the use of canvases and the importation and display of images.

So, what's going on? Well, first you do the normal applet stuff. The init method creates a button and also an instance of the class that you created that extends the Canvas class. You also load the image and then declare an instance of the OurCanvas class.

In the second class, OurCanvas, you override the default paint method for the Canvas class and create one that draws the image that you receive in the construction of the instance. Then the image is painted on the screen.

Adding to the Order Entry System


Of course, you want to incorporate the concepts of Canvases into the Order Entry system, but to what end? First, you should complete the long-standing goal of adding a graphical logo to the system. Also, it may be nice to add some sort of graphical divider between the different sections of the applet panel. This is accomplished through the use of the Canvas class and the different methods available in the Graphics class.

Adding a Logo to the Order Entry System


To add a logo to the order entry system, follow the steps outlined previously in the section on Canvases. First, declare a class that is an extension of the Canvas class, as follows:

class LogoCanvas extends Canvas {

Notice that this is not a public class. In your applet file, the only class declaration that should be public is the applet class itself.

To do some setup in the new class, define a constructor for it. This constructor accepts the logo, which is loaded in the applet itself. It sets the accepted logo as the private LogoImage variable local to this class. Then the canvas is resized to fit the logo, as follows:

    private Image LogoImage;
    LogoCanvas (Image LogoInCanvas) {
         // Get the image and place it in LogoImage. .
         LogoImage = LogoInCanvas;
         // Resize the canvas to fit the Logo exactly.
        resize (425, 87);
    }

Next, you create a paint method in the class that handles the continual updating of the display, as in the following code. The code inside the paint method draws the image onto the current graphics.

public void paint(Graphics g) {
    // Draw the logo on the canvas.
    g.drawImage(LogoImage,0,0,this);
}

And finally, declare an instance of this class in the original applet and call the constructor. Listing 9.7 shows the LogoCanvas class that is constructed along with an applet to display it. Figure 9.8 shows the resulting output.

Listing 9.7. The LogoTestApplet applet code.

import java.awt.*;
import java.applet.*;
import java.net.*;
public class LogoTestApplet extends Applet  {
    // Declare our specialized canvas declared below.
    private LogoCanvas Logo;
    public void init()  {
        setLayout(new FlowLayout());
        // Declare the logo.
        Image LogoInApplet = getImage(getDocumentBase(), "OESLogo.gif");
        // Construct the new canvas. .
         Logo = new LogoCanvas(LogoInApplet);
        // Add the logo canvas to the applet face.
        add(Logo);
    }
}
class LogoCanvas extends Canvas {
    private Image LogoImage;
    LogoCanvas (Image LogoInCanvas) {
         // Get the image and place it in LogoImage. .
         LogoImage = LogoInCanvas;
         // Resize the canvas to fit the Logo exactly.
        resize (425, 87);
    }
    public void paint(Graphics g)  {
        // Draw the logo on the canvas.
        g.drawImage(LogoImage,0,0,this);
    }
}

** 09wpj08.pcx **

Figure 9.8. The LogoTestApplet when viewed from the Appletviewer utility. This applet demonstrates the use of a canvas to incorporate graphics into containers.

Adding Graphical Dividers to the Order Entry System


One major improvement is to better divide the applet panel so the interface is easier to use and less jumbled. Horizontal bars can be used to improve the organization. To do this, create another class that extends the Canvas class and have it draw a horizontal bar the width of the applet and also display a string label in the middle of the bar. Figure 9.9 shows what one of these bars looks like.

** 09wpj09.pcx **

Figure 9.9. A sample divider that this section will create.

The first step in creating the divider is to create another class that displays the logo, as in the preceding section. Call the class HorizBar class, as follows:

class HorizBar extends Canvas {

Then make a constructor that accepts two parameters--the string to display and the width of the bar-- as follows:

    private String LineString;
    private int Width;
    HorizBar(String InString, int InWidth) {
        // Set the size of the canvas.
        resize(InWidth, 25);
        // Set the local variables equal to parameters so that
        // we can use the values in the paint method.
        Width = InWidth;
        LineString = InString;
    }

Then create the paint method, which the runtime can use to place what you want on the screen.

    public void paint(Graphics g)  {
        // Set the font and font metrics class.
        Font f = new Font("TimesRoman", Font.BOLD, 16);
        FontMetrics FM = getFontMetrics(f);
        g.setFont(f);
        // Draw a line from x = 0 to x = 15.
        g.drawLine(0, 20, 15, 20);
        // Draw the string.
        g.drawString(LineString, 20, 20);
        // Draw the rest of the line.
        g.drawLine(FM.stringWidth(LineString) + 25, 20, Width, 20);
    }

Then use it in an applet, and you're ready to go. Figure 9.10 shows this code added to the preceding LogoTestApplet.

** 09wpj10.pcx **

Figure 9.10. The LogoTestApplet with an instance of the divider class that was just added.

Audio in the Applet Package


There aren't any kind of sound capabilities incorporated into the Order Entry system. At the present time, the audio handling and production capabilities of Java are very limited. However, it is possible to load and play audio bytes. The only format that is currently supported is the AU format, or u-law.

CAUTION:


These capabilities are very limited. There are no methods to manage or cut up clips. They also do not sound very good in terms of quality. For best results, you may want to use other means such as the browser's own sound production capabilities.

Audio clips are stored using variables of the type AudioClip. One function, play, is key to playing AudioClips.

play


The play method has two forms: play(URL u) and play(URL u, String Filename). Both accept an instance of the URL class that specifies the location of the audio clip. The second function accepts the URL plus the filename.



Another method, getAudioClip(URL u, String Filename), returns an instance of the AudioClip class. You can use this to load an audio clip one time. Then you can enter MyAudioClip.play(); and it is played.


One final limitation of the audio in Java is that it cannot be used with the MediaTracker class discussed earlier in this chapter. Hopefully, in future releases of Java, the MediaTracker class will be extended to deal with audio. Expect further releases of Java to include more capabilities in terms of audio, graphics, and multimedia such as video.

The Order Entry System So Far


As of now, the Order Entry system is about 300 lines of code, and it would be a waste to make you suffer through reading a listing again. The changes made, however, were listed in this chapter. You have made some minor, though important, changes. First, you added two different canvas types: one holding a logo and a second, more generic, class that creates a labeled bar to better separate the panel. Figure 9.11 shows the Order Entry system user interface so far.

** 09pwj11.pcx **

Figure 9.11. The Order Entry system including modifications from this chapter.

The next chapter, "The Order Entry System: Exception and Error Handling and Interacting with the Browser," covers a couple of important concepts. One of these concepts is Exceptions, which are explored to see if they are useful in making the Order Entry system more robust. Also, the next chapter uses more of the applet features that allow interaction with the browser.

Previous Page Page Top TOC Next Page See Page