Home
<<Table of Contents
<<Event-Driven Programming
Bibliography>>

ANIMATING APPLETS

A static applet is a boring applet. For your applet to attract attention, it must have flicker-free animation. This can be accomplished with two very important tools for Java programmers - Multi-threading and double buffering. In this chapter, you will see how to use these two techniques in an applet with VMarquee, a refreshing approach to Java marquees.

  1. Multi-Threading
  2. Double Buffering
  3. VMarquee - A Double Buffered Applet


Top

Multi-Threading

Large tasks in Java will often force other programs, such as the browser your applet is running in, to slow down. This can be fixed with multi-threading. In an applet that utilizes multi-threading, processor intensive tasks take place inside there own "threads." Inside the thread, the applet can regularly give up processor time for other applications to run. This allows your program to run a continuous or very long task without causing all other programs to slow down to a crawl. In Java, you can create a thread by adding the "runnable" interface to your applet declaration. An "interface" is another method for adding functionality to your class. It is actually not important to understand for this application; here is an example applet declaration:

class VMarquee extends Applet implements Runnable {

Now, your applet can contain a thread. Next, you must declare the thread. The "Thread" class is contained within "java.lang."

Thread kicker;

Most programmers name their threads "kicker" but this is not required; you may name your thread whatever you want. Now that you have a thread, you have to put something in it. You usually fill your thread in the "start" event.

public void start() {
	if (kicker == null) {
		kicker = new Thread(this);
		kicker.start();
	}
}

Notice that it is contained withing an if statement. We want to make sure we do not modify the variable "kicker" if there is something in it. If the variable is empty, it is filled with a new thread. Notice that the constructor of the class "thread" accepts one parameter. This parameter must be a class that implements the interface "runnable." It just so happens that our class implements "runnable." The word "this" passes the class that it is used in as a parameter. Next, the "start" method of the class "kicker" is called. This begins the thread.
When the user stops looking at your applet, you want to stop the thread. You know the user is no longer using your applet when the "stop" event is called. You want to kill the thread in the "stop" event like so:

public void stop() {
kicker = null;
}

This will stop the thread. When the user starts using the applet again, it will call the "start" method which will start the thread again.
Now, we must put code inside of our thread. Implementing the "runnable" interface adds a new overridable method to our class named "run." It has no parameters. When you run the "start" method of the thread (like we already have), it will call the run method of class you passed to it as a parameter in its constructor. In this case, we have already passed "this" (you should always pass "this" to the thread constructor) as a parameter, so the run method called is inside the class with the thread. Inside of the "run" method, you put the code you want to run in your thread. Often, you will use a never-ending loop (not a technical term). I will demonstrate:

public void run() {
	while (true) {
		code
	}
}

This loop will run until it terminated with a "break" statement, but it will not allow any other applications to have processor time. Your loop should give up time to the processor at least once every loop. Here is how it is done:

public void run() {
	while (true) {
		code
		try {
			kicker.sleep(100);
		}
		catch(Exception e) {
			break;
		}
	}
}

You acute readers are probably wondering what that "try" is. Good question. The statement inside the "try" statement ("kicker.sleep") may fail. If it does, it throws an exception. An exception is less serious than an error. The applet can continue running when an exception is called if it is caught. That's exactly what the "try statement" does. The "try statement" is Java's version of error checking. If an exception is thrown withing a "try statement," the "catch" statement is executed. Information about the exception is stored in the "Exception" class (in this case named "e"). Because the exception is in the declaration of class "Thread's" sleep (you can check in the Java API reference) method, the method must always be called inside of a "try statement." Basically, the "sleep" statement let's other program's use the processor for the time specifed in the parameter (100 in this example).



Top


Double Buffering

In the days of DOS, programmers could use a technique known as "hardware page flipping" to produce flicker free animation. First, the program draw to an off-screen buffer; then, the page is "flipped." The buffer is drawn to the screen, and the on screen image becomes an off-screen buffer. This technique can still be used with DirectX, but not with Java. To do this, Java would have to sacrifice its platform-independence. So, we use a similar technique known as "double-buffering." In Java, this is done by creating an image to be used as a buffer. This image is drawn on, and then the image is drawn to the screen. First, the "Image" and "Graphics" classes are in the "java.awt" package so you must include a proper compiler directive. Next, you must declare the image to be used as the buffer.

Image Buffer;

That was easy enough, but the Image class is abstract. This means no "new" operator. Instead, we use a method inside the "component" class. The "Applet" class is derived from the component class, so the method is part of the "Applet" class. This is done in the "init" event. When you create the class, you must also give it a graphics context so you may draw to it. This is done with the "getGraphics" class contained within the "Image" class. Here it is:

public class Animation {
	Image Buffer;
	Graphics Context;

	public void init() {
		Buffer = createImage(100, 100);
		Context = Buffer.getGraphics();
	}
}

Just a few things to explain. The "createImage" method takes two parameters, width and height. These are are for the size of the image to be produced. The method returns an empty image. The "getGraphics" method returns a graphics context. When this context is drawn to, it modifies the image.
Now, we add a thread to complete this, and viola, we have a double-buffered applet. First, you want to change the conditions inside the thread and call the "repaint" method to update the applet. Next, you want to paint to the buffer in the paint class. After you paint to the buffer, you paint the buffer onto the screen. This will make more sense when you see it in action. Here for you viewing pleasure, is the VMarquee applet.



Top
View the source
View the source in a new window
To view the VMarquee Java Applet, use a Java-enabled browser


VMarquee - A Double Buffered Applet

Unfortunately, the source code will not fit in the small area given here. Please view the source in this window or view it in a new window.
Now, maybe I should explain a few things. Note, that in the source code a few lines will not fit on the screen. You will have to scroll to the right to see all of them.
There are a few global variables. There is there is the thread, the buffer, the graphics context, and three other things. First it the "font" class. This allows you to modify the size and font of text drawn with the "drawString" method. Next, is the String. The string class can hold text. Finally their is "VPos;" it is an integer used to hold the position of the first letter in the marquee.
The "init" statement creates the buffer and context. It then initiates the "vPos" variable. Notice how it is filled (size().height). "size" is a method included in a parent class of "Applet" that has a return variable of "Dimension." "Dimension" is a class in "java.awt" that has two public integer variables - "height" and "width." They are the height and width of the applet. Next, the String is filled. It is filled using the "getParameter" method. You can pass parameters to an applet. The "getParameter" retrieves these parameters. Here is an example applet tag with the text parameter.

<applet code=VMarquee.class width=100 height=500> <param name=text value="Hello World"> </applet>

Next of course, are the start and stop methods. They are responsible for starting and stopping the thread. The "run" method decrements the "vPos" variable. This causes the text in the marquee to move up. The "if statement" resets the variable when the text move past the top of the applet. At the end, the "repaint;" method calls the "update" method.
The "update" method is an internal method belonging to one of "applet's" parent-classes. When you call "repaint" this method is called. It paints that ugly gray background that the people who created Java seem to love so much and then calls "paint." By overriding it, we prevent it from drawing the background (which was ugly anyway) which stops the applet from flickering. Just remember, you have to include the call to the "paint" method or the screen will not be repainted.
The "paint" method is responsible for drawing to the screen. First, it draws a white background on the buffer. Then, it draws the text on the buffer. Finally, it draws the buffer to the screen. If these things were painted directly to the screen, the applet would flicker.



Home
<<Table of Contents
<<Event-Driven Programming
Bibliography>>

This is the last chapter of the book. I hope you have enjoyed it, but you are still not done learning. If you do not understand something, read about it again or find another resource. Java is a big language, and even I don't understand every little detail. Anyway, I hope you can put your new understanding of Java to good use. Good luck.