Creating a Threaded Applet
A computer term that is used often to describe the hectic pace of daily life is multitasking. (Another term is used more often around here, but the editors asked that it be omitted.) Multitasking means to do more than one thing at once--such as surfing the Web at your desk while participating in a conference call and using the Buttmaster exercise device to achieve more shapely shanks. The term comes from the world of operating systems, where a multitasking computer is one that can handle more than one program at a time.
One of the most sophisticated features of the Java language is the ability to write programs that can multitask. Under Java, each of the simultaneous tasks the computer handles is called a thread and the overall process is called multithreading. Threading is useful in animation and many other programs. This hour covers the subject of programming a threaded applet.
The following topics will be covered:
· Using an interface with a program
· Creating threads
· Starting and stopping threads
· Pausing a thread
· Loading a Web page from an applet program
· Catching errors
· Displaying an applet with other Web page elements
A Revolving-Link Applet
To provide more information on how applets are programmed, this hour is an extended workshop describing the design of a threaded applet. The program you'll be writing will rotate through a list of Web site titles and the addresses used to visit them. The following six Web sites will be listed:
· The JavaSoft Web site at
· The Gamelan Java directory at
· The JavaWorld Web magazine at
· This book's Web site at
· The Sams.net Publishing Developers' Solution Center at
· The Java Applet Ratings Service at
The title of each page and the Web address will be displayed in a continuous cycle. Users will be able to visit the currently displayed site by clicking anywhere on the applet with the mouse. This program operates over a period of time; information on each Web site must be shown long enough to be read, and the next site then will be shown. Because of this time element, threads are the best way to control the program.
Instead of entering this program into your word processor first and learning about it afterward, you'll get a chance to enter the full text of the Revolve applet at the end of the hour. Before then, each section of the program will be described.
The class Declaration
The first thing you need to do in this applet is to use import to make some classes available. The Thread class, which is part of the java.lang group of classes, comes with methods to start a thread, stop a thread, and pause a thread. All three of these methods will be useful in the Revolve applet.
The java.awt group of classes is needed because you'll be using one of them, Graphics, to display text on-screen. The java.net group will be used when you work with the Web addresses, and the java.applet group is needed when you tell the browser to load a new page. Finally, the java.awt.event group is needed to respond to mouse clicks so that a user can visit one of the addresses shown.
Use the following import statements:
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
You might be wondering why the java.lang group of classes does not need to be imported. It automatically is available to all Java programs that you write and contains a lot of the classes you will use most often. The String, Integer, and Math classes are three examples of classes that belong to java.lang.
After you have used import to make some classes available, you're ready to begin the applet with the following statement:
public class Revolve extends Applet
implements Runnable, ActionListener {
This statement creates the Revolve class as a subclass of the Applet class. It also uses a new statement called implements.
The implements statement enables this class to inherit some extra methods beyond those that were inherited from the Applet class. The Runnable and ActionListener classes are called interfaces. An interface is a special type of class that is only useful in conjunction with the implements statement. An interface extends the capabilities of a class. In this case, Runnable provides the behavior an applet needs in order to become a thread. By implementing the Runnable class, you will be able to use a run() method in this applet to make a thread begin running. The ActionListener interface enables the applet to respond to actions the user takes with the mouse. Implementing it enables the actionPerformed() method to be called when a mouse button is clicked.
Setting Up Variables
The first thing to do in the Revolve class is to create the variables and objects needed throughout the program. Create two arrays with six elements--an array of String objects called pageTitle and an array of URL objects called pageLink:
String[] pageTitle = new String[6];
URL[] pageLink = new URL[6];
The pageTitle array will store the titles of the six Web sites that will be displayed. The URL class of objects stores the value of a Web site address. URL has all the behavior and attributes that are needed to keep track of a Web address and use it to load the page with a Web browser. Both of these arrays are set up without any values at this point, so you'll have to provide them later.
The last two things to be created are an integer variable called current and a Thread object called runner:
int current = 0;
Thread runner;
The current variable will be used to keep track of which site is being displayed so that you can cycle through the sites. The Thread object runner represents the only thread this program runs. You will call methods of the runner object when you start, stop, and pause the operation of the applet.
Starting with init()
The init() method of an applet automatically is handled when the applet first starts to run. In this example, this method is used to assign values to the two arrays created for this applet, pageTitle and pageLink. It also is used to create a clickable button that will appear on the applet. The method consists of the following statements:
public void init() {
Color background = new Color(255, 255, 204);
setBackground(background);
pageTitle[0] = "JavaSoft";
pageLink[0] = getURL("http://java.sun.com");
pageTitle[1] = "Gamelan";
pageLink[1] = getURL("http://www.gamelan.com");
pageTitle[2] = "JavaWorld";
pageLink[2] = getURL("http://www.javaworld.com");
pageTitle[3] = "Java 1.1 Programming in 24 Hours";
pageLink[3] = getURL("http://www.prefect.com/java24");
pageTitle[4] = "Sams.net Developers' Resource Center";
pageLink[4] = getURL("http://www.mcp.com/sams");
pageTitle[5] = "Java Applet Rating Service";
pageLink[5] = getURL("http://www.jars.com");
Button goButton = new Button("Go");
goButton.addActionListener(this);
add(goButton);
}
The first two statements of this method set up a background color for the applet. You'll learn how to do this during Hour 16, "Using Fonts and Color in Applets."
Strings are assigned to the six elements of the pageTitle array, which stores the title of each Web page. The elements of the pageLink array are assigned a value returned by the getURL() method, which you will be creating for this program.
The last three statements of the init() method are used to create a button that will appear on-screen when the applet runs. The button has the name goButton and is labeled with the text Go. The addActionListener(this); statement makes it possible for the program to respond when the user clicks the button. The add() statement adds the button to the applet's display area. Creating components like buttons and using them in programs will be explained in detail during Hour 19, "Building a Simple User Interface," and Hour 20, "Responding to User Events."
Catching Errors as You Set Up URLs
When you set up a URL object, you must make sure that the text used to set up the address is in a valid format. and are valid, but something such as would not be because of the missing // marks.
A special try-catch statement is used to catch errors inside the program instead of letting them cause it to stop running, as many errors do. The try statement lets your program try to do something that might cause an error. If an error does occur, the catch statement is used to catch the error before it brings the program to a crashing halt.
If you're having trouble with the concept of try and catch statements, think of what it would be like to be one of Superman's best pals. Jimmy Olsen and Lois Lane can try all kinds of dangerous stunts without worrying as much about the consequences if they make an error. No narrow ledge or runaway locomotive is too risky an endeavor for them to attempt to navigate. If they try and fail, Superman will be there to catch them. No matter what you try in a Java program, you can create a catch statement that will catch errors. The getURL() method takes a string of text as an argument. The string is checked to see whether it's a valid Web address, and if it is, the method returns that valid address. If it's erroneous, the method sends back a null value. The following is the getURL() method:
URL getURL(String urlText) {
URL pageURL = null;
try { pageURL = new URL(getDocumentBase(), urlText); }
catch (MalformedURLException m) { }
return pageURL;
}
The first line of this method includes three things, in this order:
· The type of object or variable that is returned by the method--a URL object in this case. If this is void, no information is returned by the method.
· The name of the method--getURL.
· The argument or arguments, if any, that this method takes--only one in this example, a String variable called urlText.
The try statement is followed by { and } marks. The program handles any statements between these marks, and if they generate any exception or error conditions, these will be sent to the catch statement.
The catch statement also has { and } marks as part of the statement. If catch is set up to catch an error from the try block statement, anything between the { and } marks will be handled. In this example, if a MalformedURLException error occurs during the try block of statements, any statements between the { and } marks after catch will be handled. Because there are no statements between { and } in this method, catch ignores any MalformedURLException errors that occur.
If the String variable sent to the method is a valid Web address, it will be sent back as a valid URL object. If not, null is returned. Because you were assigning values to six different URL objects in the pageURL array, the getURL() method makes this process easier to do.
Handling Screen Updates in the Paint() Method
The paint() method of any applet is handled when the screen needs to be updated. This situation can be caused by the Web browser or operating system outside of the applet if they obscure part of an applet window or change its dimensions in some way. The paint() method also can be manually called within an applet when the screen needs to be updated.
If you put a repaint(); statement in an applet, it forces the paint() method to be handled. This statement is a way you can tell the program that you have done something that requires a screen update. For example, if you are writing an animation program and you move an image from one place to another, you need to use repaint(); so that the image is shown in its new location.
The Revolve applet has a short paint() method:
public void paint(Graphics screen) {
screen.drawString(pageTitle[current], 5, 60);
screen.drawString("" + pageLink[current], 5, 80);
}
The two statements inside the method display lines of text on the screen at the (x,y) positions of (5, 60) and (5, 80). The first line that is displayed is an element of the pageTitle array. The second line that is displayed is the address of the URL object, which is stored in the pageLink array. The current variable is used to determine which elements of these arrays to display.
Starting the Thread
One of the objects created for this program is a Thread object called runner. In order for a thread to get started, a place is needed where the thread is given a value and told to begin running. In this applet, the runner thread will start whenever the start() method is handled and stop whenever stop() is handled.
The start() method of an applet is handled at two different times: Right after the init() method and every time the program is restarted after being stopped. An applet is stopped any time a user switches from the applet page to another Web page. It starts again when a user returns to the original page. The following is the start() method of the Revolve applet:
public void start() {
if (runner == null) {
runner = new Thread(this);
runner.start();
}
}
This method does only one thing: If the runner thread is not already started, it creates a new runner thread and starts it. The runner object equals null when it has not been started yet, so you can test for this condition with the if statement.
The statement runner = new Thread(this); creates a new Thread object with one argument--the this statement. Using this makes the applet itself the program that will run in the runner thread.
The runner.start(); statement causes the thread to begin running. When a thread begins, the run() method of that thread is handled. Because the runner thread is the applet itself, the run() method of the applet is handled.
Running the Thread
The run() method is where the main work of a thread takes place. It is comparable to the main() block statement of a Java application. In the Revolve applet, the following represents the run() method:
public void run() {
while (true) {
repaint();
current++;
if (current > 5)
current = 0;
try { Thread.sleep(10000); }
catch (InterruptedException e) { }
}
}
All of the statements in this method are part of a while loop that has the Boolean value true as its condition. Because a while loop will continue looping as long as its condition equals true, while (true) will cause the loop to continue indefinitely. The only way the thread will stop is for the stop() method to be automatically called when the Web browser shuts down or the page containing the applet is replaced with another page.
The run() method first uses the repaint(); statement to cause the paint() method to be handled. Next, the value of the current variable increases by one, and if current exceeds 5, it is set to 0 again. The current variable is used in the paint() method to determine which Web site information to display. Changing current causes a different site to be displayed the next time paint() is handled.
This method includes another try-catch statement that handles an error that might occur. The Thread.sleep(10000); statement causes a thread to pause for 10,000 milliseconds. This statement causes the thread to wait long enough for users to read the name of the Web site and its address. The catch statement takes care of any InterruptedException errors that might occur while the Thread.sleep() statement is being handled. These errors would occur if something interrupted the thread while it was trying to sleep().
Stopping the Thread
The stop() method is handled any time the applet is stopped because the applet's page is exited, and it is the best place to stop the running thread. The stop() method for the Revolve applet contains the following statements:
public void stop() {
if (runner != null) {
runner.stop();
runner = null;
}
}
The if statement tests to see whether the runner object is equal to null. If it is, there isn't an active thread that needs to be stopped. Otherwise, the statement uses the stop() method of the runner object to stop that thread and sets runner equal to null.
Handling Mouse Clicks
Anything the user does with a mouse or keyboard in an applet is called an event, and the process of responding to events in a program is called event-handling. You'll learn all about events in Hour 20.
The last thing to take care of in the Revolve applet are mouse clicks. Whenever you click the Go button, the Web browser should open the Web site that is listed. This is done with a method called actionPerformed(). The actionPerformed() method is called whenever the button is clicked.
The following is the actionPerformed() method of the Revolve applet:
public void actionPerformed(ActionEvent evt) {
runner.stop();
AppletContext browser = getAppletContext();
if (pageLink[current] != null)
browser.showDocument(pageLink[current]);
}
The first thing that happens in this method is that the runner thread is stopped. The next two statements create a new AppletContext object called browser and check to see whether the currently displayed Web address is valid. If it is, the showDocument method of the AppletContext class is used to display a new Web page in the user's browser.
Post a Comment