Spring Semester 2003


Lecture Notes Twenty-Four: Applets, events, event handling.

Today in class I would like to discuss this code:

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

public class Game extends Applet {
    int i = 0; 
    public void paint(Graphics g) {
        this.i = this.i + 1; 
        System.out.println("Paint called: " + i); 
    }
    public void init() {
        Umpire ump = new Umpire(); 
        this.addMouseMotionListener(ump); 
    }
} 

class Umpire implements MouseMotionListener { // wearing the uniform... 
    public void mouseDragged(MouseEvent e) {
        System.out.println("Ha! You're dragging the mouse."); 
    } 
    public void mouseMoved(MouseEvent e) {
        System.out.print  ( "Mouse seen being moved at: ("); 
        System.out.println( e.getX() + ", " + e.getY() + ")"); 
    } 
} 
This goes with the following HTML file:

<html>

  <head>
    <title>Game Applet One</title>
  </head>

  <body bgcolor=white>
    <applet code="Game.class" width=300 height=300>
    </applet>
  </body>

</html>
We'd like to understand this code very well.

When this is done we will continue with the notes for tomorrow.

I include, however, some more information on applets, that we may be going over in class.

We start with the life cycle of an applet: there are four methods in the Applet class that give you the framework on which you build any serious applet:

We want to show you when these methods are called and what code you should place into them.
init()
This method is used for whatever initializations are needed for your applet. This works much like a constructor - it is automatically called by the system when Java launches the applet for the first time. Common actions in an applet include processing PARAM values and adding GUI components.

Note: applets can have a default constructor, but it is customary to perform all initialization in the init method, instead of the default constructor.

start()
This method is automatically called after Java calls the init method. It is also called whenever the user returns to the page containing the applet after having gone off to other pages. This means that the start method can be called repeatedly, unlike the init method. For this reason, put the code that you want executed only once in the init method, rather than in the start method. For example the start method is where you usually restart a thread for your applet, for example, to resume an animation.

If your applet does nothing that needs to be suspended when the user leaves the current Web page, you do not need to implement this method (or the stop method discussed next).

stop()
This method is automatically called when the user moves off the page on which the applet sits. It can, therefore, be called repeatedly in the same applet. The purpose is to give you a chance to stop a time-consuming activity from slowing down the system when the user is not p[aying attention to the applet. Your should not call this method directly. If your applet does not perform animation, play audio files, or perform calculations in a thread, you do not usually need to use this method.

destroy()
Unlike the finalize method for objects, Java is guaranteed to call this method when the browser shuts down normally. Since applets are meant to live on an HTML page, you do not need to worry about destroying the panel. This will happen automatically when the browser shuts down. What you do need to put in the destroy method is the code for reclaiming any non-memory dependent resources such as window handles that you may have consumed. (Of course Java calls stop method before calling the destroy method if the applet is still active).

Of the four the most important (customizable) by far is paint().

Here's an investigation into how paint() works:

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

public class One extends Applet {
    int i = 0; 
    public void paint(Graphics g) {
	i += 1; 
	System.out.println("paint has been called: " + i + " times."); 
    } 
} 
And use a basic HTML file to dispatch the applet.

<html>
  <head>
    <title>All eyes on the mouse!</title>
  </head>
<body>
  <applet code=One.class height=300 width=300>

  </applet>
</body>
</html>
Now let's make paint work harder.
import java.applet.*;
import java.awt.*;
import java.awt.event.*;

public class One extends Applet {
    int i = 0; 
    public void paint(Graphics g) {
	i += 1; 
	System.out.println("paint has been called: " + i + " times."); 
	int width = getWidth(), height = getHeight(); 
	for (int line = 0; line < height; line += 3) {
	    g.drawLine(0, line, width, line); // horizontal line 
	} 
    } 
} 
Now let's introduce some colors, and let's show them.
import java.applet.*;
import java.awt.*;
import java.awt.event.*;

public class One extends Applet {
    int i = 0; 
    Color[] c = { Color.red    , Color.yellow, Color.blue , Color.pink, 
		  Color.magenta, Color.green , Color.black, Color.white }; 
    public void paint(Graphics g) {
	i += 1; 
	System.out.println("paint has been called: " + i + " times."); 
	int width = getWidth(), height = getHeight(); 
	int j = 0; 
	for (int line = 0; line < height; line += 3) {
	    g.setColor(c[j % c.length]); 
	    g.drawLine(0, line, width, line); 
	    j += 1; 
	} 
    } 
} 
Now let's paint in one color, but each time another one.
import java.applet.*;
import java.awt.*;
import java.awt.event.*;

public class One extends Applet {
    int i = 0; 
    Color[] c = { Color.red    , Color.yellow, Color.blue , Color.pink, 
		  Color.magenta, Color.green , Color.black, Color.white }; 
    public void paint(Graphics g) {
	i += 1; 
	System.out.println("paint has been called: " + i + " times."); 
	int width = getWidth(), height = getHeight(); 

	for (int line = 0; line < height; line += 3) {
	    g.setColor(c[i % c.length]); 
	    g.drawLine(0, line, width, line); 

	} 
    } 
}
Now it is easy to prove that paint is actually optimized.

It only refreshes that part of the screen that has just become visible.

Now we add circles.

import java.awt.*; public class Circle {
    int x, y, radius; 
    public Circle(int x, int y, int radius) {
	this.x = x; this.y = y; this.radius = radius; 
    } 
    public void moveTo(int x, int y) { // x, y coordinates of center 
	this.x = x - radius; 
	this.y = y - radius; 
    } 
    public void draw(Graphics g) {
	g.drawOval(x, y, 2 * radius, 2 * radius); 
    } 
} 
And we draw them.
import java.applet.*;
import java.awt.*;

public class One extends Applet {
    Circle c = new Circle(20, 20, 10); 
    public void paint(Graphics g) {
	c.draw(g); 
    } 
} 
Now let's pay attention to mouse movement.

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

public class One extends Applet implements MouseMotionListener {
    Circle c = new Circle(20, 20, 10); 
    public void init() {
	addMouseMotionListener(this); 
    } 
    public void paint(Graphics g) {
	c.draw(g); 
    } 
    public void mouseMoved(MouseEvent e) {
	int x = e.getX(), y = e.getY();
	c.moveTo(x, y); 
	repaint(); 
    }
    public void mouseDragged(MouseEvent e) {

    }
} 
And notice that you can leave the circle behind while dragging.

And here's one last example (which is still instructive, I believe).

This is a simple applet whose purpose is to draw:

import java.applet.*;
import java.awt.*;
import java.util.*;

public class ManyShapes extends Applet
{
    // this method overrides the paint method from the Applet class 
    public void paint(
                      Graphics g  // the Graphics context to draw with 
                      )
    {
        // create a new number generator 
        Random r = new Random();
        
        // draw 10000 shapes 
        for(int i = 0; i < 10000; i++)
            {
                // generate random values for our shape 
                int x = r.nextInt()%300;
                int y = r.nextInt()%300;
                int width  = r.nextInt()%300;
                int height = r.nextInt()%300;
                
                // set a random color          
                g.setColor(new Color(r.nextInt()));
                
                // generate a positive number between 0 and 4 
                int n = Math.abs(r.nextInt()%5);
                
                // draw a shape based on the value of n 
                switch(n)
                    {
                    case(0):
                        g.draw3DRect(x, y, width, height, true);
                        break;
                    case(1):
                        g.drawRect(x, y, width, height);
                        break;
                    case(2):
                        g.drawOval(x, y, width, height);
                        break;
                    case(3):
                        g.fillRect(x, y, width, height);
                        break;
                    case(4):
                        g.fillOval(x, y, width, height);
                        break;
                        
                        // this shouldn't happen; but if it does, 
                        // print a message 
                    default:
                        System.out.println("Invalid case: " + n); 
                        break;
                    } // switch
            } // for 
    } // paint
} // ManyShapes
Here's the HTML file:
<html>

  <head>
    <title>ManyShapes</title>
  </head>

  <body>

    <hr>

    <applet code=ManyShapes.class
            width=300
            height=300>

    </applet>

    <hr>

    </body>

</html>
EXERCISES


Last updated: Apr 6, 2003 by Adrian German for A201