import java.awt.*; import java.awt.event.*; import java.applet.*; import java.util.*; public class BouncingBallsSol extends Applet { private static int width; private static int height; private Choice choice; private TextArea echoArea; private BallThread t; private Vector balls; private int lastX; private int lastY; private int clickNumber; public void init ( ) { setBackground(Color.white); height = getBounds().height; width = getBounds().width; addMouseListener(new MouseHandler()); // Create a button and add it to the Frame. Button clearButton = new Button("Clear"); clearButton.setForeground(Color.black); clearButton.setBackground(Color.lightGray); add(clearButton); clearButton.addActionListener(new ClearButtonHandler()); // Create a menu of user choices and add it to the Frame. choice = new Choice(); choice.addItem("Magenta"); choice.addItem("Yellow"); choice.addItem("Blue"); choice.addItem("Green"); add(choice); choice.addItemListener(new ChoiceHandler()); // Create a TextArea and add it to the Frame. echoArea = new TextArea(2, 50); echoArea.setEditable(false); add(echoArea); } // init public void start ( ) { clickNumber = 0; balls = new Vector(); t = new BallThread(balls); t.start( ); } // start public void stop () { t.stopBallThread(); } // stop public void paint(Graphics g) { Enumeration e = balls.elements(); while (e.hasMoreElements()) { Ball b = (Ball)(e.nextElement()); b.paint(g); } } private class BallThread extends Thread { boolean alive; Vector balls; public BallThread (Vector balls) { this.balls = balls; alive = true; } public synchronized void stopBallThread () { //substitutes stop() which is deprecated alive = false; } public synchronized boolean isLiving () { return alive; } public void run( ) { while (isLiving()) { Enumeration e = balls.elements(); while (e.hasMoreElements()) { Ball b = (Ball)(e.nextElement()); b.move(); } repaint( ); try { Thread.sleep(50); } catch (InterruptedException exc) { } } } } private class Ball { int x, y; // current location int dx, dy; // speed int diameter = 10; Color color; public Ball (int x, int y, int dx, int dy, Color color) { this.x = x; this.y = y; this.dx = dx; this.dy = dy; this.color = color; } public void move () { if (x < 0 || x >= BouncingBallsSol.width) dx = - dx; if (y < 0 || y >= BouncingBallsSol.height) dy = - dy; x += dx; y += dy; } public void paint (Graphics g) { g.setColor(color); g.fillOval(x, y, diameter, diameter); } } // Ball // Handling events that occur in the frame // Called when the user clicks the mouse button private class MouseHandler extends MouseAdapter { public void mouseClicked(MouseEvent e) { int x = e.getX(); int y = e.getY(); echoArea.setText("Mouse Clicked at " + e.getX() + ", " + e.getY() + "\n"); clickNumber = clickNumber + 1; // is it the first click? if (clickNumber % 2 == 1) { echoArea.append("Click in another point to set direction and speed"); lastX = x; lastY = y; } // or the second? else { String c = choice.getSelectedItem(); if (c.equals("Magenta")) balls.addElement(new Ball(lastX,lastY,(x-lastX)/10,(y-lastY)/10,Color.magenta)); else if (c.equals("Blue")) balls.addElement(new Ball(lastX,lastY,(x-lastX)/10,(y-lastY)/10,Color.blue)); else if (c.equals("Yellow")) balls.addElement(new Ball(lastX,lastY,(x-lastX)/10,(y-lastY)/10,Color.yellow)); else balls.addElement(new Ball(lastX,lastY,(x-lastX)/10,(y-lastY)/10,Color.green)); } } // mouseClicked } // Called when the user selects clear Button private class ClearButtonHandler implements ActionListener { public void actionPerformed (ActionEvent e) { echoArea.setText("Clear button selected "); repaint(); t.stopBallThread(); clickNumber = 0; balls = new Vector(); t = new BallThread(balls); t.start( ); } } // Called when the user selects a Choice private class ChoiceHandler implements ItemListener { public void itemStateChanged (ItemEvent e) { String c = (String) (e.getItem()); echoArea.setText("Color selected: " + c); // prepare to handle first mouse click for this choice clickNumber = 0; echoArea.append("\nClick to set starting position of new ball"); } } } // BouncingBallsSol