Download Using Threads in Animation

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
Programming in Java 6 with Swing and Servlets Part 1
Exercise: Threads and Exception
Handling
This exercise teaches what threads are, and why they are useful in Java applications. The
lab focuses on incorporating threads within Java applets, a common technique used by
applet programmers.
Without the use of threads, processes that should work in the background will often, in
reality, monopolize all the resources in the system. If an applet needs a piece of code that
may run for a long period of time, such as an animation loop or a complex computation, it
should be put in a thread. The Java virtual machine running with the browser calls the
applet’s init(), start(), stop(), and destroy() methods, and expects them
to return after performing their tasks.
A common mistake made by beginning applet programmers is to place code in the
init() or start() methods (or a method called by them) to build a GUI interface and
wait for a user event. When this code executes, the methods are prevented from returning
control to the browser, which puts the applet in a deadlocked state. The only way to stop
the applet when this happens is to issue a kill, interrupt, or break instruction from the
command line.
The way to avoid this problem is to place the code called by init() or start() in a
separate thread, thereby allowing control to return to the browser. This exercise
illustrates this technique.
Part One: A Simple Applet
Create an applet that simply displays the time and date.
1. For ModuleSeven create the c:\labs\ModuleSeven directory.
2. Create a new Java application called DigClock.java that extends a Swing JApplet
object. Import the following packages. Access to Swing classes is obtained by
importing the javax.swing package.
3. Add these two instance variables to the class for a font and date. Override JApplet’s
init(), start() and stop() methods (we’ll use these later). In the paint()
method add code to paint the current date and time to the applet’s window. Your new
JApplet should look something like this:
Copyright ©2008, Custom Training Institute. All rights reserved.
Threads and Exception Handling -Exercise: Page 2
import java.awt.*;
import java.util.Date;
import javax.swing.*;
public class DigClock extends JApplet
{
private Font fnt = new Font("Helvetica", Font.BOLD, 16);
private Date theDate = new Date();
public void init()
{
super.init();
getContentPane().setSize(400,100);
}
public void start()
{
}
// the applet is running.
public void stop()
{
}
// the applet is stopping
public void paint(Graphics g)
{
super.paint(g);
g.setFont(fnt);
g.drawString(theDate.toString(),5,40);
}
}
4. Use your text file to create another HTML page and embed the DigClock applet.
(copy MyApplet.html from ModuleThree and modify it if you like). The new
DigClock.html should look like the following:
Copyright ©2008, Custom Training Institute. All rights reserved.
Threads and Exception Handling -Exercise: Page 3
<HTML>
<HEAD>
<TITLE>DigiClock</TITLE>
</HEAD>
<BODY>
<APPLET code="DigClock.class">
</APPLET>
<p>The Digital Clock </p>
</BODY>
</HTML>
5. View DigClock in your browser or use the appletviewer that comes with
the java development kit. DigClock displays a digital clock that only changes
when the applet is refreshed or after browsing to another web page and using the
browser’s Back button. The clock is only refreshed when the paint() method is
called. DigClock looks something like this when running:
Writing Applets Using Threads
The clock can be made to update once per second by adding a thread of execution that
sleeps for a second then calls the applet’s paint() method.
Copyright ©2008, Custom Training Institute. All rights reserved.
Threads and Exception Handling -Exercise: Page 4
6. Make the applet runnable by implementing the Runnable interface. Runnable
requires that we add a method called run(). An instance variable for a thread is
added that will execute the run method in a separate thread of execution. The threaded
version of the DigClock is shown in the box below:
import java.awt.*;
import java.util.Date;
import javax.swing.*;
public class DigClock extends JApplet implements Runnable
{
private Font fnt = new Font("Helvetica", Font.BOLD, 16);
private Date theDate = new Date();
Thread myThread;
private volatile boolean keepRunning = true;
public void init()
{
super.init();
getContentPane().setSize(400,100);
}
public void start()
{
if (myThread == null)
{
myThread = new Thread(this);
keepRunning = true;
myThread.start();
}
}
public void run()
{
while( keepRunning )
{
theDate = new Date();
repaint();
try { Thread.sleep(1000); }
// pause for 1000 milliseconds (1 second)
catch (InterruptedException e) { /* ignored */ }
Copyright ©2008, Custom Training Institute. All rights reserved.
Threads and Exception Handling -Exercise: Page 5
}
}
public void stop()
{
if (myThread != null)
{
keepRunning = false; // this will stop the while loop in the run method
myThread = null;
}
}
public void paint(Graphics g)
{
super.paint(g);
g.setFont(fnt);
g.drawString(theDate.toString(),5,40);
}
}
7. Save your file and compile the DigClock.java.
8. Use your browser or the appletviewer to load MyApplet.html.
The digital clock now updates once per second. Threads allow the applet to display the
date in a separate thread without interfering with the browser. Note that even though a
method from the Thread class (sleep) is used to pause the execution of the thread, the
applet itself is not affected. The internal thread stops when we browse to another web
page and restarts if we return to the DigClock page.
The sleep() method is a static method of the Thread class used to pause execution of
a program.
The volatile boolean variable keepRunning is used to start and stop the
thread. Threads should be stopped in a controlled way, such as using a controlling
variable, as in this exercise. The volatile modifier requests that the Java virtual
machine always read the shared copy of the variable and forces synchronized access to
the variable when it is accessed from concurrent running threads.
The stop() method does two things: it stops the thread from executing, and it sets the
thread’s variable myThread to null. Setting the variable to null makes the Thread
object it previously contained available for removal from memory at the java virtual
Copyright ©2008, Custom Training Institute. All rights reserved.
Threads and Exception Handling -Exercise: Page 6
machine’s discretion. If the viewer comes back to this Web page with this applet, the
start() method creates a new thread, and the clock begins running again..
Part Two: Using Threads in Animation
This example illustrates how threads are used to implement simple animations in applets.
The program will draw an alternately expanding and shrinking circle using thread
techniques and some basic graphics routines from the Abstract Windowing Toolkit. The
circle will expand to fill the application area. Define the applet width and height to be of
size 300.
The program will create an expanding and shrinking solid red circle on a blue
background. The following code sets the background color:
setBackground(Color.blue);
prior to running the loops that control the expanding and shrinking. A solid red circle is
created by the fillOval() method in the java.awt.Graphics class. Consider an
oval to be a rectangle with overly rounded corners. The fillOval()method takes
these four arguments: the x and y coordinates of the top left corner of the overly-rounded
rectangle, and the width and height of the oval itself. To create a circle, make the width
and height equal. When the circle expands or shrinks, the top left corner coordinate will
travel along a diagonal from the center of the applet region to the top left corner of the
applet region. For example, this instruction creates a solid circle having a diameter of
300 and whose top left corner is at (0,0):
g.fillOval(0,0,300,300);
Call the applet that runs the thread Balloon. Because it uses threads, Balloon will
implement the Runnable interface. The Balloon class will have these four methods:
start(), stop(), run(), and paint(). The start() and stop() methods
behave as described above in Part One for applets that run threads. The run() method
contains the body of the applet. The run() method should set the initial background
color. Then it should contain code for two loops that execute alternately, one for the
expanding circle, and one for the shrinking circle. Each loop should call repaint() to
display the recalculated circle.
The paint() method performs the display, setting the color of the circle using this
method:
g.setColor(Color.red);
and then displaying the circle using the fillOval() method described above. The
circle should continue to expand and shrink as long as the applet is running.
Copyright ©2008, Custom Training Institute. All rights reserved.
Threads and Exception Handling -Exercise: Page 7
1. Create a new java application called Balloon.java that extends a Swing Applet and
implements Runnable.
2. Ignore the error at the line defining the Balloon class. This error indicates that the
run() method has not yet been implemented. Add the following import
statement:
import java.awt.*;
3. Add the following instance variables:
private
private
private
private
Thread myThread = null;
int xydiag, diam;
int rad = 150;
volatile boolean keepRunning = true;
4. Add these start() and stop() methods:
public void start()
{
if (myThread == null)
{
myThread = new Thread(this);
keepRunning = true;
myThread.start();
}
}
public void stop()
{
if (myThread != null)
{
keepRunning = false;
myThread = null;
}
}
5. Modify the init() method to set the size of the applet as follows:
public void init()
{
super.init();
getContentPane.setSize(rad*2, rad*2);
}
6. Implement the run() method:
public void run()
Copyright ©2008, Custom Training Institute. All rights reserved.
Threads and Exception Handling -Exercise: Page 8
{
setBackground(Color.blue);
while(keepRunning)
{
for(xydiag = rad; xydiag >= 0; xydiag -= 5)
{
diam = 2 * (rad - xydiag);
repaint();
try { Thread.sleep(100); }
catch (InterruptedException e){}
}
for(xydiag = 0; xydiag <= rad; xydiag += 5)
{
diam = 2 * (rad – xydiag);
repaint();
try{ Thread.sleep(100); }
catch (InterruptedException e){}
}
}
}
7. Implement the paint() method:
public void paint(Graphics g)
{
super.paint(g);
g.setColor(Color.red);
g.fillOval(xydiag, xydiag, diam, diam);
}
8. Save your work and compile the program.
9. Create another web page to contain the new applet. An example web page is shown
below:
<html>
<head>
<title>Balloon</title>
</head>
<body>
<applet code="Balloon.class" width="400" height="400">
</applet>
<p> Balloons </p>
Copyright ©2008, Custom Training Institute. All rights reserved.
Threads and Exception Handling -Exercise: Page 9
</body>
</html>
10. Open the web page in your browser or use the appletviewer and you should see
the red circle expanding and contracting.
Copyright ©2008, Custom Training Institute. All rights reserved.
Threads and Exception Handling -Exercise: Page 10
Solutions
DigClock.java
import java.awt.*;
import java.util.Date;
import javax.swing.*;
/**
* A threaded applet that displays a working digital clock
* on its panel.
*/
public class DigClock extends JApplet implements Runnable
{
/** the digital clock face is rendered in this font */
private Font fnt = new Font("Helvetica", Font.BOLD, 16);
/** the initial date displayed on the clock */
private Date theDate = new Date();
/** thread that runs the clock */
Thread myThread;
/** as long as this is true the thread will continue running. It is
* declared volatile since multiple threads may access its value.
*/
private volatile boolean keepRunning = true;
/**
* Override JApplet.init to set the size of
* the content panel.
*/
public void init()
{
super.init();
getContentPane().setSize(400, 100);
}
/**
* Override JApplet.start to create and start a thread.
*/
public void start()
{
if(myThread == null)
{
Copyright ©2008, Custom Training Institute. All rights reserved.
Threads and Exception Handling -Exercise: Page 11
myThread = new Thread(this);
keepRunning = true;
myThread.start();
}
}
/**
* Implementation of the Runnable interface. This method
* runs the digital clock.
*/
public void run()
{
while(keepRunning)
{
theDate = new Date();
repaint();
try
{
Thread.sleep(1000);
}
catch(InterruptedException e) {}
}
}
/**
* Override JApplet.stop to kill the running thread.
*/
public void stop()
{
if(myThread != null)
{
keepRunning = false;
myThread = null;
}
}
/**
* Draw the clock on the applets panel.
* @param g The graphics context.
*/
public void paint(Graphics g)
{
super.paint(g);
Copyright ©2008, Custom Training Institute. All rights reserved.
Threads and Exception Handling -Exercise: Page 12
g.setFont(fnt);
g.drawString(theDate.toString(), 5, 40);
}
}
DigClock.html
<html>
<head>
<title>DigClock</title>
</head>
<body>
<applet code="DigClock.class" width="400" height="125">
</applet>
<p> The Digital Clock </p>
</body>
</html>
Balloon.java
import java.awt.*;
import javax.swing.*;
/**
* A threaded applet that draws ballons (circles) on its
* primary graphics panel.
*/
public class Balloon extends JApplet implements Runnable
{
private Thread myThread = null;
private int xydiag;
private int diam;
private int rad = 150;
private volatile boolean keepRunning = true;
/**
* Override JApplet.init to set the size of
* the content panel.
*/
public void init()
{
Copyright ©2008, Custom Training Institute. All rights reserved.
Threads and Exception Handling -Exercise: Page 13
super.init();
getContentPane().setSize(rad * 2, rad * 2);
}
/**
* Override JApplet.start to create and start a thread.
*/
public void start()
{
if(myThread == null)
{
myThread = new Thread(this);
keepRunning = true;
myThread.start();
}
}
/**
* Override JApplet.stop to kill the running thread.
*/
public void stop()
{
if(myThread != null)
{
keepRunning = false;
myThread = null;
}
}
/**
* Implementation of the Runnable interface. This method
* runs the balloon application.
*/
public void run()
{
setBackground(Color.blue);
while(keepRunning)
{
for(xydiag = rad; xydiag >= 0; xydiag -= 5)
{
diam = 2 * (rad - xydiag);
repaint();
try
Copyright ©2008, Custom Training Institute. All rights reserved.
Threads and Exception Handling -Exercise: Page 14
{
Thread.sleep(100);
}
catch(InterruptedException e) {}
}
for(xydiag = 0; xydiag <= rad; xydiag += 5)
{
diam = 2 * (rad – xydiag);
repaint();
try
{
Thread.sleep(100);
}
catch(InterruptedException e) {}
}
}
}
/**
* Draw the applets main panel.
* @param g The graphics context.
*/
public void paint(Graphics g)
{
super.paint(g);
g.setColor(Color.red);
g.fillOval(xydiag, xydiag, diam, diam);
}
}
Balloon.html
<html>
<head>
<title>Balloon</title>
</head>
<body>
<applet code="Balloon.class" width="400" height="400">
Copyright ©2008, Custom Training Institute. All rights reserved.
Threads and Exception Handling -Exercise: Page 15
</applet>
<p> Balloons </p>
</body>
</html>
Copyright ©2008, Custom Training Institute. All rights reserved.