Title: Events
Course: CPS 261: Advanced Java Concepts ~ DL & MM MASTER

Events

Here's how it works.

- For each event that you may be interested in, there is an Interface which defines routines that are associated with the interface. For example, there is a MouseListener Interface that has 5 routines associated with it (mouseClicked, mouseEntered, mouseExited, mousePressed, and mouseReleased).
- If you want to be aware of the events that are part of a Listener interface, you must have a class that implements the Listener Interface that interests you. It can be your Applet class.
- For each Component in your program where you want to be aware of a particular interface, you must register a class with the component that implements the desired interface. For the MouseListener interface, your component will need an addMouseListener routine to register the MouseListener interface.
- Each Component has the capability to "Fire" certain Component specific Events. Firing an Event results in packaging the event's information in an appropriate Event structure and calling an appropriate Interface routine. In the case of the MouseListener Interface, the appropriate event structure is called the MouseEvent.

Sounds pretty complicated, doesn't it. Before I give a simple example, I want to give you a reasonably complete list of the AWT JDK 1.1 Interfaces, Events, routines that you need to be aware of.

AWT Listeners Information

We have already looked at the following example, but we had a different emphasis (i.e. Paint/Repaint) the last time we looked at this example:

Spots.java


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

public class Spots extends Applet
        implements MouseListener{
    Point clickPoint=new Point(-1,-1);
    int radius = 7;

    public void init()
    {
    // Our Applet is a Component.  We want to register it to
    // fire MouseEvents according to the MouseListener interface
    // The class which will handle this interface in the Applet itself.
    // This implies our applet must implement the MouseListener interface.

       addMouseListener(this);
    }

    public void paint(Graphics g)
    {
       // find out how big our drawing area is
       int w = getSize().width;
       int h = getSize().height;
       // Make a red spot
       Color color = new Color(1.0f, 0.0f, 0.0f);

       g.drawRect(0,0,w -1, h -1); // draw boundary

       if (clickPoint.x >= 0)
       {
          g.setColor(color);
          g.fillOval(clickPoint.x - radius,    clickPoint.y - radius,
                    2*radius, 2*radius);
       }
    }
    public void mousePressed(MouseEvent e)
    {
       clickPoint.x = e.getX();
       clickPoint.y = e.getY();
       // Note that nothing happens unless I tell java to repaint my screen
       repaint();
    }

    public void mouseClicked(MouseEvent e) {}
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}
    public void mouseReleased(MouseEvent e) {}

    public static void main(String[] args) {
        Spots applet = new Spots();
        Frame aFrame = new Frame("Spots");

        aFrame.add(applet);
        aFrame.setSize(380,200);
        // Normally the following call comes from the Browser
        applet.init();

        aFrame.setVisible(true);
    } // end of main


}


Click to make points

Take a look at the above code. Here are the key issues in this example:

- The MouseListener Interface is what we want to connect to. We will have our Applet class implement this interface. This implies that our Applet must implement all 5 routines that are part of the MouseListener interface. We don't have to do anything useful in all 5 of these routines, but these routines do have to be implemented somewhere.
- In our init routine we will call the routine addMouseListener. A lot is happening here. The Component that will fire the MouseEvent is the Component that is part of our Applet class. In later examples, the component may be a Button class that you have just created. The addMouseListener routine wants to be passed an instance of a class that implements the MouseListener interface. In our case that will be our Applet class.
- When a Mouse is pressed, we will find ourselves in the MousePressed routine.

Inner Classes

One New Java feature that is often used when dealing with the new JDK 1.1 event model is the notion of Inner Classes. An Inner Class is a class that is defined inside of an existing class. The inner class is only accessable to the class containing the inner class. Also the inner class has access to all of the member variables in its containing class. We will redo the Spots program again using an inner class.


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

public class SpotsInner extends Applet
{
    Point clickPoint=new Point(-1,-1);
    int radius = 7;

// ****************************************************
//   INNER CLASS

    class MouseStuff implements MouseListener
    {
        public void mouseClicked(MouseEvent e){}
        public void mouseEntered(MouseEvent e){}
        public void mouseExited(MouseEvent e) {}
        public void mouseReleased(MouseEvent e){}

        // Finally the one routine we really use in this Interface
        public void mousePressed(MouseEvent e)
        {
// Note how this Inner class has access to all of the characteristics of
// the outer class which contains this inner class
            clickPoint.x = e.getX();
            clickPoint.y = e.getY();
            // Note that nothing happens unless I tell java to repaint my screen
            repaint();
        }
    }
 // ****************************************************


    MouseStuff mouse_stuff=new MouseStuff();


    public void init()
    {
        addMouseListener(mouse_stuff);
    }

    public void paint(Graphics g)
    {
        int w = getSize().width;
        int h = getSize().height;
        Color color = new Color(1.0f, 0.0f, 0.0f);

        g.drawRect(0,0,w -1, h -1);

        if (clickPoint.x >= 0)
        {
            g.setColor(color);
            g.fillOval(clickPoint.x - radius,    clickPoint.y - radius,
                    2*radius, 2*radius);
        }
    }
}


Note that instead of having the Applet class implement the MouseListener class, we create another class called MouseStuff inside the Applet. Note that now we have to create an instance of this class and pass the instance to the addMouseListener routine. Also note that when you compile this source file you will see 2 class files. If you put this on your web site, you would need to put both class files on your web site.

Adapter Classes

Suppose that when you are interested in dealing with the MouseListener interface, you don't like the fact that you have to add 5 routines to your class, when you really only care about one of the routines. In this case you might be interested in the Adapter classes that are associated with all of the Listener interfaces with more than one routine.

Take another look at the AWT Listeners Information table. Note that all of the listener interfaces that have more than one routine also have Adaper routines. An Adapter class is a class that implements a given interface and has all of the required routines implemented as do nothing type routines. This means that if we create an Inner class derived from an Adapter class and override only the routine we want, we won't have to look at all of the other routines that we want to ignore.


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

public class SpotsAdapter extends Applet
{
    Point clickPoint=new Point(-1,-1);
    int radius = 7;

// ****************************************************
//   INNER CLASS

    class MouseStuff extends MouseAdapter
    {
       // Note that we don't need don't need to specify any of the methods that
       // we don't care about.  The MouseAdapter has already implemented all
       // methods in the Interface as dummy routines.

       // We just override the methods we really care about.

        public void mousePressed(MouseEvent e)
        {
            clickPoint.x = e.getX();
            clickPoint.y = e.getY();
            // Note that nothing happens unless I tell java to repaint my screen
            repaint();
        }
    }
 // ****************************************************


    MouseStuff mouse_stuff=new MouseStuff();


    public void init()
    {
        addMouseListener(mouse_stuff);
    }

    public void paint(Graphics g)
    {
        int w = getSize().width;
        int h = getSize().height;
        Color color = new Color(1.0f, 0.0f, 0.0f);

        g.drawRect(0,0,w -1, h -1);

        if (clickPoint.x >= 0)
        {
            g.setColor(color);
            g.fillOval(clickPoint.x - radius,    clickPoint.y - radius,
                    2*radius, 2*radius);
        }
    }
}




Note that MouseStuff is now an inner class derived from MouseAdapter. MouseAdapter takes care of all of the routines that we have no interest in. In MouseStuff we override only the routines we care about.

Anonymous Classes

Another variation on the Inner Class theme is to create a class that is defined in place and never really given any name. I personally think that Anonymous Classes are a little hard to read, but you may encounter this technique in some other book, so it's good to be aware of it.


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

public class SpotsAnonymous extends Applet
{
    Point clickPoint=new Point(-1,-1);
    int radius = 7;

    public void init()
    {
    // Anonymous class created here
        addMouseListener(
            new MouseAdapter()
            {
                public void mousePressed(MouseEvent e)
                {
                    clickPoint.x = e.getX();
                    clickPoint.y = e.getY();
                    repaint();
                }  //end of mousePressed routine
            } // end of Anonymous Class definition
        ); // end of addMouseListener call
    }

    public void paint(Graphics g)
    {
        int w = getSize().width;
        int h = getSize().height;
        Color color = new Color(1.0f, 0.0f, 0.0f);

        g.drawRect(0,0,w -1, h -1);

        if (clickPoint.x >= 0)
        {
            g.setColor(color);
            g.fillOval(clickPoint.x - radius,    clickPoint.y - radius,
                    2*radius, 2*radius);
        }
    }
}


TextField, TextArea Interfaces

- TextFields - receive ActionEvents when the enter key is entered if you add an ActionListener class to your text component
- TextListener - The TextListener interface can be used to find out any time the text contents changes. The second text field in this example publishes its contents everytime a change occurs.

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

public class Text1 extends Applet {
  TextField txtNormal = new TextField(50);
  TextArea txtOutput = new TextArea(5,50);
  public void init() {

  // This demonstrates that the ActionListener Interface works
  // for TextFields, and TextAreas just like buttons.  The equivalent
  // to clicking on a Button in a TextField is hitting the Enter Key

    txtNormal.addActionListener(new MyTxtActionListener());

  // A special interface for TextFields is the TextListener which
  // is invoked everytime the TextField changes values

    txtNormal.addTextListener(new MyTxtChangedListener());
    add(txtNormal);
    add(txtOutput);
  }

// Inner Class for the TextListener Interface
  class MyTxtChangedListener implements TextListener {
    public void textValueChanged(TextEvent e) {
      txtOutput.setText("Something Changed:\n"+
            txtNormal.getText()+" \n");
    }
  }

  // Inner class for the ActionListener Interface
  class MyTxtActionListener implements ActionListener {
      public void actionPerformed(ActionEvent e) {

        txtOutput.setText("Enter Key: \n"+
            txtNormal.getText() +" \n");
    }
  }


}


Taking Control of Your Text Boxes

- KeyListener - Normally you let the Textfield/TextArea deal with keystrokes automatically. However, you can hook into the KeyListener interface and handle characters yourself. The text box in this example grabs the Key characters and Upper cases them before they get displayed. Take a look at this field in IE. Note that the field looks like it is not editable. That's because we had to call setEditable(false) to keep IE from doubling the characters. Comment out the setEditable call and note that IE and Netscape act differently.



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

public class Text2 extends Applet {

  TextField txtSpecial = new TextField(30);

  public void init() {

    txtSpecial.setEditable(false);
    txtSpecial.addKeyListener(new MyTxtKeyListener());
    add(txtSpecial);
  }
  // Inner class for KeyListener Interface
  class MyTxtKeyListener extends KeyAdapter {

    public void keyTyped(KeyEvent e) {
      int nlen;
      String ts = txtSpecial.getText();

      if(e.getKeyChar() !=  KeyEvent.VK_BACK_SPACE)
        ts += Character.toUpperCase( e.getKeyChar());
      else if ( ts.length() > 0) // Make sure not empty
        ts = ts.substring(0, ts.length() - 1);

      txtSpecial.setText(ts);
      nlen = txtSpecial.getText().length();
      txtSpecial.setCaretPosition(nlen);
      // Stop regular character from appearing:
      e.consume();
    }
  }

}


A lot of Listener Interfaces

The following example attempts to define a lot of interfaces just to show that it can be done. Normally one would never need or want so many Listener interfaces. Since there are a lot of System.out.printlns, this applet is good to view in the appletviewer. To use the appletviewer, you can use the following HTML:

<applet code="ManyListeners.class" width="400" height="250">
</applet>

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

public class ManyListeners extends Applet {

  Button   b1  = new Button("        Wide  Button             ");
  TextField t = new TextField(50);
  TextField t2 = new TextField(50);

  Applet me=this;

  Big theListener = new Big();

  public void init() {
    b1.addActionListener(theListener);
    b1.addFocusListener(theListener);
    b1.addKeyListener(theListener);
    b1.addMouseListener(theListener);
    b1.addMouseMotionListener(theListener);

    me.addFocusListener(theListener);
    me.addKeyListener(theListener);
    me.addMouseListener(theListener);
    me.addMouseMotionListener(theListener);
    me.addComponentListener(theListener);

    add(b1);
    add(t);
    add(t2);
  }


  class Big implements ActionListener, FocusListener,
    KeyListener, MouseListener, MouseMotionListener,
    ComponentListener
    {


// Routine to get the Component Source of the Event
    String source(EventObject e){
              String src="unknown source ", outstr;
              if (e.getSource() == b1)
                        src = "Button  ";
              if (e.getSource() == me)
                        src = "Applet ";

              return src;
        }

// Routine to report Event Type
    private void out(EventObject e, String s){
        String outstr;
        outstr = source(e) +s;
        System.out.println(outstr);
        t.setText(outstr);
    }

//****************************************
// ActionListener Stuff
    public void actionPerformed(ActionEvent e) {
                out(e, "ActionListener: ");
        }


//****************************************
// FocusListener Stuff
    public void focusGained(FocusEvent e) {
                out(e, "focusGained: ");
            }
    public void focusLost(FocusEvent e) {
                out(e, "focusLost: ");
            }


//****************************************
// KeyListener Stuff
    private String keyInfo(KeyEvent e){
         int nc ;
         char c;
         nc  =e.getKeyCode();
         c = e.getKeyChar();
         String str= " key("+ c + "," + nc+ ") = " + e.getKeyText(nc);
         return str;
    }

    public void keyPressed(KeyEvent e) {
                out(e, "keyPressed: " + keyInfo(e));
            }
    public void keyReleased(KeyEvent e) {
                out(e, "keyReleased: " + keyInfo(e));
            }
    public void keyTyped(KeyEvent e) {
                out(e, "keyTyped: " + keyInfo(e));
            }

//****************************************
 // MouseListener Stuff
    public void mouseClicked(MouseEvent e) {
                out(e, "mouseClicked: ");
            }
    public void mouseEntered(MouseEvent e) {
                out(e, "mouseEntered: ");
            }
    public void mouseExited(MouseEvent e) {
                out(e, "mouseExited: ");
            }
    public void mousePressed(MouseEvent e) {
                out(e, "mousePressed: ");
            }
    public void mouseReleased(MouseEvent e) {
                out(e, "mouseReleased: ");
            }

//****************************************
   // MouseMotionListener Stuff
    public void mouseDragged(MouseEvent e) {
                  Point pt=e.getPoint();
                 t2.setText(source(e) + " mouseDragged: " + pt.x +"," +pt.y);
            }
    public void mouseMoved(MouseEvent e) {
                  Point pt=e.getPoint();
                 t2.setText(source(e) + " mouseMoved: " + pt.x +"," +pt.y);
            }

 //****************************************
   // ComponentListener Stuff
    public void componentHidden(ComponentEvent e){
            out(e, "componentHidden: ");
            }
    public void componentShown(ComponentEvent e){
            out(e, "componentShown: ");
            }
    public void componentMoved(ComponentEvent e){
            out(e, "componentMoved: ");
            }
    public void componentResized(ComponentEvent e){
            out(e, "componentResized: ");

            Dimension d;
            System.out.println("************************************");
            d = me.getPreferredSize();
            System.out.println(" Preferred Size(width, height)=(" + d.width +
                "," + d.height + ")");

            d = me.getMinimumSize();
            System.out.println(" Minimum Size(width, height)=(" + d.width +
                "," + d.height + ")");

            d = me.getMaximumSize();
            System.out.println(" Maximum Size(width, height)=(" + d.width +
                "," + d.height + ")");

            Rectangle r;
            r = me.getBounds();
            System.out.println(" Actual Size(width, height)=(" + r.width +
                "," + r.height + ")");

            }// End of componentResized
  } // End of Big Inner Class
} // End of ManyListeners Class


WindowListener Interface

The following example is a pure Frame application and it ties into the Window Listener interface. The primary reason I have used this interface is the windowClosing method. Usually, I just want to call System.exit(0) when this method occurs. I added logic to display the events in this Listener interface including the windowClosing method. To allow you to see the windowClosing message, I made this task wait for 2 seconds before calling System.exit(0).


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

public class WindowStuff extends Frame
    implements WindowListener
{
    TextArea toutput = new TextArea(4,60);

    public WindowStuff() {

        add(toutput);
        addWindowListener(this);
     }

     public void windowOpened(WindowEvent e){
        toutput.append("windowOpened\n");
     }

    public void windowClosing(WindowEvent e){
        toutput.append("windowClosing\n");
        // Wait for 2 seconds so you see this message
        try
        {
            Thread me = Thread.currentThread();
            me.sleep(2000);

            // Now lets get out of here!!!
            System.exit(0);

        }catch (InterruptedException ex){}
    }

    public void windowClosed(WindowEvent e){
        toutput.append("windowClosed\n");
    }

    public void windowActivated(WindowEvent e){
        toutput.append("windowActivated\n");
    }

    public void windowDeactivated(WindowEvent e){
        toutput.append("windowDeactivated\n");
    }

    public void windowIconified(WindowEvent e){
        toutput.append("windowIconified\n");
    }

    public void windowDeiconified(WindowEvent e){
        toutput.append("windowDeiconified\n");
    }


  public static void main(String[] args) {
    WindowStuff aFrame = new WindowStuff();

    aFrame.setSize(600,250);
    aFrame.setVisible(true);
  } // end of main
}


For Fun - One More Applet Using Listener Interfaces

Al Gore's Opinion Poll - This was sent to me from one of my former students

Exercises

Last Modified: April 22, 2003 9:32 AM