Example Program 2

Below, is a second example program. It draws within a panel contained in an external rrame. It displays up to ten balls which move around the screen following a randomly selected trajectory. Balls can be added or deleted by pressing the appropriate buttons, and the movement of the balls stopped andd restarted. A fifth button allows the user to quit the applet.

Each ball runs as a separate thread, with all threads drawing to the same image. That image is then displayed at once on the panel.

import java.applet.*;
import java.awt.*;
import java.awt.event.*;

public class Balls extends Applet implements ActionListener {

MyFrame outerBox;

Panel drawPanel, bottomPanel, buttonPanel;
Button addButton, deleteButton, startButton, stopButton, quitButton;
TextField message;

Ball balls [];
int current = - 1;

Image offscreenImage;
Graphics offscreenImageG;
Graphics drawPanelG;
Dimension d;

    public void init() {

        buildUI ();

        d = drawPanel.getSize ();
        drawPanelG = drawPanel.getGraphics ();

        offscreenImage = this.createImage ( d.width, d.height );
        offscreenImageG = offscreenImage.getGraphics ();
        offscreenImageG.setColor ( Color.white );
        offscreenImageG.fillRect ( 0, 0, d.width, d.height );

        balls  = new Ball [ 10 ];

        run ();

    }  // end init



    public void run ( )  {

        while ( true )  {

            try {Thread.sleep ( 20 );} catch ( InterruptedException e) {;}
            repaint ();

        }  // end while

    }  // end run

// ************* update

    public void update ( Graphics g )  {

        paint ( g );

    }  // end update


// ************* paint

    public void paint ( Graphics g )  {

        drawPanelG.drawImage ( offscreenImage, 0, 0, this );

    }  // end paint


//***********  Utility Methods   ***********


  public void buildUI ()  {

    drawPanel = new Panel ( );
    drawPanel.setBackground ( Color.white );

    // *** build the buttonPanel panel

    buttonPanel = new Panel ( );

    addButton = new Button ( "Add" );
    deleteButton = new Button ( "Delete" );
    startButton = new Button ( "Start" );
    stopButton = new Button ( "Stop" );
    quitButton = new Button ( "Quit" );

    addButton.addActionListener ( this );
    deleteButton.addActionListener ( this );
    startButton.addActionListener ( this );
    stopButton.addActionListener ( this );
    quitButton.addActionListener ( this );

    buttonPanel.add ( addButton );
    buttonPanel.add ( deleteButton );
    buttonPanel.add ( stopButton );
    buttonPanel.add ( startButton );
    buttonPanel.add ( quitButton );

    // *** build the message display area

    message = new TextField ( "Messages Displayed Here", 80 );
    message.setEditable ( false );


    // *** build the bottom panel

    bottomPanel = new Panel ( );

    bottomPanel.setLayout ( new BorderLayout ( ) );
    bottomPanel.add ( "North", buttonPanel );
    bottomPanel.add ( "South", message );
    bottomPanel.setBackground (Color.white);

    outerBox = new MyFrame (  );

    outerBox.addWindowListener ( outerBox );
    outerBox.add ( "Center", drawPanel );
    outerBox.add ( "South", bottomPanel );

    outerBox.resize ( 500, 400 );

    outerBox.show ();

  }  // end buildUI



  //***********  Interface Methods   ***********



  //****  ActionListener methods

  public void actionPerformed ( ActionEvent e )  {

    Object s = e.getSource();

    if ( s == addButton )  {
        if ( current < 9 )  {
            ++current;
            balls [current] = new Ball ( offscreenImageG, d );
            balls[current].start();
            message.setText ( (current+1)+" ball(s); room for "+(9-current)+" more." );
        }  // end if
        else  {
            message.setText ( "Maximum number of balls exceeded." );
        }  //  end else

    }  //  end addButton

    if ( s == deleteButton )  {
        synchronized ( offscreenImageG ) {
            balls[current].delete();
            balls[current].stop();
        }  // end synchronized
        --current;
        message.setText ( "Ball deleted; room for "+(9-current)+" more." );
    }  //  end deleteButton

    if ( s == startButton )  {
        for ( int i = 0; i <= current; i++ )  {
            balls[i].resume();
            message.setText ( "Action resumed." );
        }  // end for

    }  //  end startButton

    if ( s == stopButton )  {
        for ( int i = 0; i <= current; i++ )  {
            balls[i].suspend();
        }  // end for
        message.setText ( "Action suspended." );
    }  //  end stopButton

    if ( s == quitButton )  {
        for ( int i = 0; i <= current; i++ )  {
            balls[i].stop();
        }  // end for
        message.setText ( "Applet quitting." );
        outerBox.hide ();
        outerBox.dispose ();
        System.exit (0);
    }  //  end stopButton


  }  // end actionPerformed


} // end Balls



//*******************************  Ball Class  ****************


class Ball extends Thread  {

Graphics g;
Dimension d;
int delay;
static Random random = new Random();

int x, y;
long inc, xinc, yinc, theta;
int left, right, top, bottom;
Color color;
int diameter;

    Ball ( Graphics dg, Dimension dd ) {
        super ();
        g = dg;
        d= dd;
        init ();
    }  // end constructor


    public void run ()  {

        try  {
            while ( true )  {
                synchronized ( g ) {
                    g.setColor ( Color.white );
                    g.fillOval ( x, y, diameter, diameter );
                    moveBall ();
                    g.setColor ( color );
                    g.fillOval ( x, y, diameter, diameter );
                }  // end synchronized
                sleep ( delay );
            }  // end while
        }  // end try
        catch ( InterruptedException except)  {
            System.out.println ( "Interrupt in Ball" );
            return;
        }  // end catch

    }  // end run


    private void init () {

        diameter = 50;
        inc = 3;

        delay = 15 - (int) (10 * random.nextFloat() );

        boolean test = true;
        while ( test )  {
            x = (int)( (d.width - diameter) * random.nextFloat () );
            y = (int)( (d.height - diameter) * random.nextFloat () );
            if ( ( x > 5 ) && ( y > 5 ) ) test = false;
        }  // end while

        test = true;
        while ( test )  {
            theta = (long)( 360 * random.nextFloat () );
            xinc = (long)(inc * Math.cos ( theta ) );
            yinc = (long)(inc * Math.sin ( theta ) );
            if ( (Math.abs(xinc) > 1 ) &&  (Math.abs(yinc) > 1) ) test = false;
        }  // end while

        left = 0;
        right = d.width - diameter;
        top = 0;
        bottom = d.height - diameter ;

        int rd = (int)( 255 * random.nextFloat () );
        int gr = (int)( 255 * random.nextFloat () );
        int bl = (int)( 255 * random.nextFloat () );
        color = new Color ( rd, gr, bl );

    }  // end init


    public void delete ()  {

        g.setColor ( Color.white );
        g.fillOval ( x, y, diameter, diameter );

    }  // end delete;


//***********  Utility Methods   ***********


    private void moveBall ()  {

        if ( (int)(x + xinc) > right || (int)(x + xinc) < left )  {
            xinc = -1 * xinc;
        }
        else x = (int)(x + xinc);

        if ( (int)(y + yinc) > bottom || (int)(y + yinc) < top )  {
            yinc = -1 * yinc;
        }
        else y = (int)(y + yinc);

    }  // end moveBall



}  // end Ball


Run the applet