// DrawJPanel4.java // Demos a JPanel used as a dedicated drawing area // Listens to its own mouse events // Uses anonymous inner class // Uses arrays for the three balls // Priovides for suspending and resuming of threads import java.awt.*; import java.awt.event.*; import javax.swing.*; public class DrawJPanel4 extends JPanel implements Runnable { private int width, height; private int k = 0; // counter for balls private final int NUMBALLS = 3; private Color colors[ ] = { Color.red, Color.green, Color.blue }; private int x[ ] = new int[ NUMBALLS ]; // arrays of x and y coordinates private int y[ ] = new int[ NUMBALLS ]; private int xMove[ ] = new int[ NUMBALLS ]; // x and y "speeds" private int yMove[ ] = new int[ NUMBALLS ]; private boolean isBall[ ] = new boolean[ NUMBALLS ]; // does ball exist private Thread threads[ ] = new Thread[ NUMBALLS ]; private boolean suspended[ ] = new boolean[ NUMBALLS ]; // is ball suspended private int index; public DrawJPanel4( ) { initialize( ); addMouseListener( new MouseAdapter( ) { public void mousePressed( MouseEvent e ) { if ( k > 2 ) return; isBall[ k ] = true; x[ k ] = e.getX( ) - width / 2; // make mouse in center y[ k ] = e.getY( ) - height / 2; // make mouse in center threads[ k++ ].start( ); repaint( ); } } ); } // utility method to initialize arrays private void initialize( ) { for ( int i = 0; i < NUMBALLS; i++) { xMove[ i ] = ( int ) ( 5 * Math.random( ) + 1 ); yMove[ i ] = ( int ) ( 5 * Math.random( ) + 1 ); } for ( int i = 0; i < NUMBALLS; i++ ) { isBall[ i ] = false; } for ( int i = 0; i < NUMBALLS; i++ ) { threads[ i ] = new Thread( this, "Ball "+ i ); } } public void run( ) { Thread executingThread = Thread.currentThread( ); while ( true ) { // sleep for .01 seconds try { Thread.sleep( 10 ); synchronized( this ) { while ( suspended[ index ] && threads[ index ] == executingThread ) wait( ); } } catch ( InterruptedException ex ) { ex.printStackTrace( ); } for ( int i = 0; i < NUMBALLS; i++ ) { if ( executingThread == threads[ i ] ) { x[ i ] += xMove[ i ]; if ( x[ i ] >= 940 || x[ i ] <= 4 ) xMove[ i ] *= -1; // reverse direction if wall is hit y[ i ] += yMove[ i ]; if ( y[ i ] >= 438 || y[ i ] <= 4 ) yMove[ i ] *= -1; // reverse direction if wall is hit } } repaint( ); } } public void drawingStuff( int w, int h ){ // receives two size arguments from applet width = w; height = h; repaint( ); // calls paintComponent } // all of the actual drawing takes place here public void paintComponent( Graphics g ) { // call to super class super.paintComponent( g ); // my drawing code g.setColor( Color.blue ); g.drawRect( 3, 3, 989, 490 ); g.drawRect( 4, 4, 987, 488 ); for ( int i = 0; i < NUMBALLS; i++ ) { if ( isBall[ i ] ) { g.setColor( colors[ i ] ); g.fillOval( x[ i ], y[ i ], width, height ); } } } // method for suspending and resuming the threads public synchronized boolean flip( int i ) { index = i; suspended[ i ] = !suspended[ i ]; System.out.println( "Thread " + i + " is suspended?" + suspended[ i ] ); if ( !suspended[ i ] ) notify( ); return suspended[ i ]; } public synchronized void stop( ) { // stop threads everytime stop is called // as the user browses another web page for ( int i = 0; i < threads.length; i++ ) threads[ i ] = null; notifyAll( ); } }