In the bouncing ball applet each ball is animated by its own slave thread. New balls are created by mouse clicks. Keyboard inputs stop, suspend, and resume the balls:
If you have a JDK 1.1 enabled browser, the applet is located at:
http://www.cs.sjsu.edu/faculty/pearce/java1/threads/balls/bounce.html
import java.awt.*;
import java.awt.event.*;
import java.util.*; // for Vector
import java.applet.*;
public class Bounce extends Applet {
// client area metrics
protected int xUpperLeft, yUpperLeft,
xLowerRight, yLowerRight;
private Vector balls;
private int ballDiam;
private Random numberGen;
private boolean paused;
private void killAll() {
showStatus("Killing all
balls");
for(int i = 0; i < balls.size();
i++) {
Ball b =
(Ball)balls.elementAt(i);
b.stop();
}
balls.removeAllElements();
repaint();
}
private void resumeAll() {
if (paused) {
showStatus("Resuming all
balls");
paused = false;
for(int i = 0; i <
balls.size(); i++) {
Ball b =
(Ball)balls.elementAt(i);
if (!b.isAlive())
showStatus("This ball
is dead!");
b.resume();
}
}
}
private void suspendAll() {
if (!paused) {
showStatus("Suspending all
balls");
paused = true;
for(int i = 0; i <
balls.size(); i++) {
Ball b =
(Ball)balls.elementAt(i);
b.suspend();
}
}
}
public void start() {
updateMetrics(); resumeAll(); }
public void stop() { suspendAll(); }
public void destroy() { killAll(); }
public void init() {
addMouseListener(new
MouseEventHandler());
addKeyListener(new
KeyEventHandler());
Object parent = getParent();
balls = new Vector();
ballDiam = 10;
numberGen = new Random();
paused = false;
}
protected void
updateMetrics() {
Dimension d = getSize();
Insets in = getInsets();
int clientWidth = d.width - in.right
- in.left;
int clientHeight = d.height -
in.bottom - in.top;
xUpperLeft = in.right;
yUpperLeft = in.top;
xLowerRight = xUpperLeft +
clientWidth;
yLowerRight = yUpperLeft +
clientHeight;
}
class KeyEventHandler
extends KeyAdapter {
public void keyTyped(KeyEvent e) {
// int key = e.getKeyCode(); //
always 0!
char key = e.getKeyChar();
if (key == 'k') killAll();
else if (key == 'r') resumeAll();
else if (key == 's')
suspendAll();
else showStatus("key pressed
= " + key);
}
}
class MouseEventHandler
extends MouseAdapter {
public void mouseClicked(MouseEvent
e) {
showStatus("New Ball");
Point p = e.getPoint();
Ball b = new Ball(p.x, p.y);
balls.addElement(b);
b.start();
}
public void mouseReleased(MouseEvent
e) {
showStatus("");
}
}
public void
paint(Graphics g) {
for(int i = 0; i < balls.size();
i++) {
Ball b =
(Ball)balls.elementAt(i);
g.setColor(b.color);
g.fillOval(b.xc, b.yc, ballDiam,
ballDiam);
}
}
// slave thread
class Ball extends Thread {
public int xc, yc;
private int dx, dy, oldxc, oldyc,
red, green, blue;
public Color color;
public Ball(int x, int y) {
xc = x;
yc = y;
dx = numGen.nextInt() % 7 - 3;
dy = numGen.nextInt() % 7 - 3;
int max = Thread.MAX_PRIORITY +
Thread.MIN_PRIORITY + 1;
int pri = (numGen.nextInt() %
max) - Thread.MIN_PRIORITY;
red = numberGen.nextInt() % 256;
blue = numberGen.nextInt() % 256;
green = numberGen.nextInt() %
256;
color = new Color(red, green,
blue);
}
private void move() {
oldxc = xc;
oldyc = yc;
xc += dx;
yc += dy;
if (xc <= xUpperLeft ||
xLowerRight <= xc)
dx = -dx;
if (yc <= yUpperLeft ||
yLowerRight <= yc)
dy = -dy;
}
public void run() {
while(true) {
move();
repaint(oldxc, oldyc, 2 *
ballDiam, 2 * ballDiam);
try { Thread.sleep(5); }
catch(InterruptedException e)
{}
}
}
}
} // Bounce
<HTML>
<TITLE> Bouncing Balls </TITLE>
<BODY>
Mouse click creates a ball. Press s to suspend, r to resume, and k to
kill.<BR>
<APPLET CODE="Bounce.class" WIDTH=300 HEIGHT=500>
Sorry, your browser can't show applets.
</APPLET>
</BODY>
</HTML>