CSC 8310 -- Animated Applets

Dr. David Matuszek,   dave@acm.org
Fall 1998, Villanova University

When you write an applet, you usually put buttons and other user controls on the screen. You attach Listeners to these, and, when user input occurs, a method in the Listener (usually named something like actionPerformed) responds to the input.

If your applet is "animated" (continuously drawing to the screen), then it must be in an infinite loop to do that work. If it's in an infinite loop, then it can't be listening for user events. So you need to create a separate thread, and put your infinite loop in that new thread; then the original thread can do its job of listening for events. You can start and stop this new thread any time you want to.

Every thread must have a method run(); this is kind of like main() for that thread, except for all your initializations (which you should have done in your init() method). It can have any other methods you like, but run() is the only one it must have.

There are at least two ways to do this:

  1. Create a subclass of Thread and put your run() method in it. This is probably easier to understand, but sometimes getting to the variables you need is a little trickier, since they're back in your applet class. (If you put your Thread subclass inside your Applet subclass, this helps quite a bit.)

  2. Have the applet itself implement the Runnable interface. When you do this, the run() method goes right into your applet class. This might be a little confusing at first, but it really works the same way, and you avoid problems accessing variables because everything is in the same class. (This is the way the Threads example works.)
Here are skeleton applets that demonstrate the two methods. The relevant changes are shown in brown.

Subclassing Thread Implementing Runnable
import java.applet.*;
import java.awt.*;
import java.awt.event.*;

class MyApplet extends Applet implements Runnable
{
  // Delarations of "global" variables go here.
  // Declarations of parameters also go here.
  Thread anotherThread;
  boolean running = false;
  
  public void init ()
  {
    // Set up the applet layout, add buttons
   //   text fields, etc., and their Listeners.
   // Get parameters using getParameter ().
   // Do initializations (set up arrays, etc.)
   //   so that you are ready to run().
  }

  public void start ()
  {
    if (!running)
    {
      anotherThread = new Thread (this);
      anotherThread.start ();
      running = true;
      // There probably isn't much else to do here.
    }
  }

  public void stop ()
  {
    if (running)
    {
      anotherThread.stop ();
      running = false;
      // There probably isn't much else to do here.
    }
  }

  public void paint (Graphics g)
    {
      // Do one animation step here or in run().
      // Draw everything that isn't drawn for you.
    }

  // Since MyApplet implements Runnable, the run()
  // method must be a method of MyApplet.
  public void run ()
  {
    while (true)
      {
        // Do one animation step here or in paint().
        repaint ();
        // Maybe slow down the animation.
        try { Thread.sleep (100); }
        catch (InterruptedException e) { };
      }
  }
}
import java.applet.*;
import java.awt.*;
import java.awt.event.*;

class MyApplet extends Applet // doesn't implement
{                             //   Runnable.
  // Delarations of "global" variables go here.
  // Declarations of parameters also go here.
  MyThread anotherThread;
  boolean running = false;
  
  public void init ()
  {
    // Set up the applet layout, add buttons
   //   text fields, etc., and their Listeners.
   // Get parameters using getParameter ().
   // Do initializations (set up arrays, etc.)
   //   so that you are ready to run().
  }

  public void start ()
  {
    if (!running)
    {
      anotherThread = new MyThread ();
      anotherThread.start ();
      running = true;
      // There probably isn't much else to do here.
    }
  }

  public void stop ()
  {
    if (running)
    {
      anotherThread.stop ();
      running = false;
      // There probably isn't much else to do here.
    }
  }

  public void paint (Graphics g)
    {
      // Do one animation step here or in run().
      // Draw everything that isn't drawn for you.
    }

  class MyThread extends Thread
  {
    public void run ()
    {
      while (true)
        {
          // Do one animation step here or in paint().
          repaint ();
          // Maybe slow down the animation.
          try { Thread.sleep (100); }
          catch (InterruptedException e) { };
        }
    }
  }
}