When Java was released to the public in late 1995, its creators had some lofty intentions for the programming language. It was going to revolutionize the way software was produced and distributed, remove the need to write versions of a program for different operating systems, and take full advantage of the Internet as a place to run programs. (They probably wanted to make some money, too.) Although some notable projects created since then with Java advance those goals, many Java programmers worked under somewhat less noble motivation: show-and-tell.
For every human who gets a kick out of advancing the causes of humankind, bettering society, and being the wind beneath someone's wings, there's another who did something because it looked cool. Animated Java applets are a case in point. There are dozens of different special-effects applets on the Web that do interesting things with text and graphics. During this hour you'll set aside the greater good of Javakind and create one of your own.
The following topics will be covered:
One of the common uses for Java applets has been to animate text or images on a World Wide Web page. This kind of animation can be done as an attention-getting move; an online catalog might use moving text to inform visitors of sale items, for example. It also can be done to provide information in a more dynamic way. Several media organizations, such as CNN and ESPN, have used Java applets as a way to provide constant news and sports updates.
A lot of these applets move graphics or text over a static background to produce an interesting effect. You're going to take the opposite tack with the Pan applet. It will keep something in the foreground still while the background moves. The effect could be useful to draw attention to text or create an interesting logo for a company.
The Pan applet uses the same threaded applet structure that you have used in several of the past hours. A thread called runner is created in the applet's start() method and destroyed in the stop() method. The runner object calls the run() method of the program, which loops continuously while the program runs.
Three Image objects are used in the program: back, fore, and workspace. The first two objects hold the background image and foreground image that will be displayed. The third is used as an off-screen work area to make the animation appear more smoothly, a trick called double-buffering that you learned during Hour 18, "Creating Animation."
In addition to displaying the background and foreground images, the applet can display a line of text. This text and both images are specified in parameters on the Web page that runs the applet. You can use the following parameters:
All text and images are displayed in the paint() method of the Pan applet. An off-screen Graphics object is used for all drawing methods, and when everything has been drawn, the off-screen area is copied to the applet window. Using double-buffering produces much better results than displaying each image and string in the window individually.
If a line of text is specified as a parameter, the applet will center it horizontally and vertically on-screen. This is done using a class called FontMetrics, which reports on how large a line of text will be if displayed in a specific font, size, and style. The following statements create a Font object and set up a FontMetrics object that is linked to it:
Font f = new Font(fontName, Font.BOLD, fontSize); FontMetrics fm = getFontMetrics(f);
The Font object is used as an argument to the getFontMetrics() method. Once you create the FontMetrics object, you can use two of its methods to help you determine how to center a line of text in that font. These methods are stringWidth(), which indicates how wide the text will be, and getHeight(), which reveals how tall anything in the font will be. In the Pan applet you're going to create, the following statements use these methods:
int xStart = (size().width - fm.stringWidth(text)) / 2; int yStart = size().height/2 + fm.getHeight()/4; offscreen.drawString(text, xStart, yStart);
The size().width and size().height statements are the dimensions of the applet window itself. By using these statements with the FontMetrics methods, the program can determine the right location for the text.
Figure 23.1 shows the Pan applet with a line of text centered in the applet window. It's a little harder to distinguish in black and white, but the text is drawn twice--once in black and again in white. The text is drawn at a slightly different place the second time, as shown in the following statement:
offscreen.drawString(text, xStart-2, yStart-2);
This statement creates a shadow effect that makes the text easier to see over the background.
Figure 23.1. The output of the Pan applet running on the Web page Pan.html.
To create the effect of an image panning from right to left, the Pan applet takes advantage of the way images are displayed with Java. Before taking a look at this applet, you should get Pan running. Create a new file in your word processor called Pan.java, and enter Listing 23.1 into the file. Save it when you're done.
1: import java.awt.*; 2: 3: public class Pan extends java.applet.Applet implements Runnable { 4: Thread runner; 5: Image back, fore, workspace; 6: Graphics offscreen; 7: String text; 8: String fontName; 9: int fontSize = 24; 10: int x1 = 0; 11: int x2; 12: 13: public void init() { 14: workspace = createImage(size().width, size().height); 15: offscreen = workspace.getGraphics(); 16: // get parameters 17: String imageBack = getParameter("background"); 18: if (imageBack != null) 19: back = getImage(getDocumentBase(), imageBack); 20: String imageFore = getParameter("foreground"); 21: if (imageFore != null) 22: fore = getImage(getDocumentBase(), imageFore); 23: x2 = size().width; 24: text = getParameter("text"); 25: fontName = getParameter("font"); 26: if (fontName == null) 27: fontName = "Arial"; 28: String param = getParameter("fontsize"); 29: if (param != null) 30: fontSize = Integer.parseInt("0" + param); 31: } 32: 33: public void start() { 34: if (runner == null) { 35: runner = new Thread(this); 36: runner.start(); 37: } 38: } 39: 40: public void stop() { 41: if (runner != null) { 42: runner.stop(); 43: runner = null; 44: } 45: } 46: 47: public void run() { 48: while (true) { 49: repaint(); 50: try { Thread.sleep(200); } 51: catch (InterruptedException e) {} 52: x1 = x1 - 1; 53: x2 = x2 - 1; 54: if (x1 <= (size().width * -1)) 55: x1 = size().width; 56: if (x2 <= (size().width * -1)) 57: x2 = size().width; 58: } 59: } 60: 61: public void paint(Graphics screen) { 62: offscreen.drawImage(back, x1, 0, null); 63: offscreen.drawImage(back, x2, 0, null); 64: if (fore != null) 65: offscreen.drawImage(fore, 0, 0, null); 66: if (text != null) { 67: offscreen.setColor(Color.black); 68: Font f = new Font(fontName, Font.BOLD, fontSize); 69: FontMetrics fm = getFontMetrics(f); 70: offscreen.setFont(f); 71: int xStart = (size().width - fm.stringWidth(text)) / 2; 72: int yStart = size().height/2 + fm.getHeight()/4; 73: offscreen.drawString(text, xStart, yStart); 74: offscreen.setColor(Color.white); 75: offscreen.drawString(text, xStart-2, yStart-2); 76: } 77: screen.drawImage(workspace, 0, 0, this); 78: } 79: 80: public void update(Graphics screen) { 81: paint(screen); 82: } 83: }
Compile this file with the javac compiler tool, and then return to the word
processor to create a Web page that contains the Pan applet. Enter Listing
23.2 and save it as Pan.html. Note that the width and height
attributes of the <APPLET> tag should be the same dimensions as the
background image to achieve the best results.
1: <applet code="Pan.class" width=460 height=43> 2: <param name="background" value="patch.gif"> 3: <param name="font" value="Helvetica"> 4: <param name="fontsize" value="25"> 5: <param name="text" value="FRED'S APPETITE SUPPRESSANTS"> 6: </applet>
Before you can see this applet running on a page, you need to put a copy of the image
file patch.gif in the same directory as Pan.html. You can find
this file on the book's CD-ROM in the Win95nt4/Book/Source/Hour23 directory.
You also can retrieve a copy from the book's official Web site at http://www.prefect.com/java24.
Take the link from the site's front page labeled Hour 23's Moving Images,
and you'll be able to download patch.gif. Get a copy of two other image
files called samsback.gif and samslogo.gif also to save time later.
When you use appletviewer to load this Web page, you will see the Fred's Appetite Suppressants banner shown in Figure 23.1. No foreground element is specified on the page, so the text appears over a moving background.
By using parameters to load all images and text, the Pan applet is able to vary its performance greatly. You can create a new Web page by using different images and different parameters. Return to your word processor and create a new file called Sams.html. Enter the text of Listing 23.3 and save the file.
1: <applet code="Pan.class" width=229 height=166> 2: <param name="background" value="samsback.gif"> 3: <param name="foreground" value="samslogo.gif"> 4: </applet>
As with the previous example, you need to copy some image files before loading this
Web page into appletviewer. The files are samsback.gif and samslogo.gif.
As shown in Figure 23.2, this applet shows a moving background underneath a static
logo of Sams.net Publishing. The Sams logo makes use of transparency so that the
background image can be seen.
The panning effect used by this applet is possible because of the way the drawImage() method can be drawn to off-screen coordinates. Normally, when you draw an image to an applet window or a workspace, the (x, y) coordinates that you specify are within the display area of the program. Otherwise, the graphics can't be seen. However, there's no prohibition against drawing to coordinates that make most of an image appear off-screen. The drawImage() method will display the portion of the image that does appear on-screen and disregard the rest.
Figure 23.2. The output of the Pan applet running on the Web page Sams.html.
By drawing the background image twice at different positions, the Pan program makes the image seem to move. The exact positions of the images vary as the program runs, which creates the animation effect, but they always are shown right next to each other. Figure 23.3 shows how this happens with the Sams.html page. Black borders have been drawn around the background image so that you can see that it is being drawn twice. The thick black border indicates the visible display area of the applet--everything outside of it would not be seen.
Figure 23.3. Two copies of the background image partially displayed in the applet window.
The Pan applet uses the integer variables x1 and x2 to determine the two x coordinates where the background should be drawn. The images do not move up and down, so no y coordinates are needed. The x1 variable begins with the value of 0, and x2 starts out at the width of the applet: 229. The first time that the images are displayed, one copy will be shown at (0,0), filling the entire window, and the other will begin at (229,0), one pixel off the right edge.
In Lines 52-53 of the program, both x1 and x2 are reduced by 1. When the repaint() method is called next, each image is displayed one pixel to the left of its last position. Lines 54-56 make sure that neither of the images goes so far to the left that none of it is displayed. If the image moves too far to the left, the x coordinate is set to the width of the applet.
The Pan applet is an example of producing an interesting visual effect with a few lines of programming. Most of the statements in the program are used to load parameters, store images, and handle the display of nonmoving graphics and text. Less than a dozen lines control the values of x1 and x2, and these are all that's needed to move the two copies of the background image and produce the animation.
As you create your own programs and start looking at the programs that others make available on the World Wide Web, you'll pick up more of these tricks. Many of them will probably be used more for the grown-up version of show-and-tell--the home page--than any higher purpose.
However, you might find some practical uses for these programs in unexpected places. Using some of the same logic that was needed for the Pan applet, you could write an applet that displays a small section of a large map and enables users to interactively pan to other places on the map. It isn't an achievement on par with the polio vaccine or interleague play in Major League Baseball, but a map applet of that kind could be useful to many people browsing the World Wide Web. Because it works fully in conjunction with Web pages, Java makes some types of information more accessible than they would be otherwise. And that's something to get animated about.
Don't pan past this section of the book without testing your know-how by answering the following questions.
Unless you're ready to Pan this hour's subject matter, do the following activities: