Visual human interfaces allow a uer to interact with a computer program. The user may click a button, resize a window, enter text into a field, etc. The components of the Graphical User Interface, as seen by the rest of the program, are involved in ``events'' and usually other parts of the program will react to these events. A class may register with an event generator as a listener for that event from that generator. When an event occurs, each of the registered listeners is notified automatically by the Java runtime environment. It is then up to the listener to react if it wants to.

This module assumes you have already read the notes on "User Interfaces" and "Event Handling Techniques" where a number of techniques were lsited. Here in this module the event handling techniques of Java are discussed.

In a later module, "Basic GUI", more details of components will emerge. At this stage I don't want to confuse you with too many concepts at once.

Events in Java

In Java, components such as buttons, mice and keyboards generate events. Events are descended from java.awt.AWTEvent (see Deitel figure 12.5), and are in the four subclasses:

The ComponentEvent is further subclassed into

An ActionEvent is the event type with which we will mostly be involved. An ItemEvent is also common and is involved where there are a number of items involved, e.g. a drop down menu or radio buttons.

There are plenty of examples in Deitel chapters 12 and 13 in particular, as well as in other chapters.

Event Listeners in Java

In Java, there are 11 listener interfaces from java.util.EventListener (see Deitel figure 12.6):

To handle an event, a class must provide a method which implements the appropriate interface as defined. Deitel defines an ``event handler'' as a ``method that is automatically called in response to a particular type of event.''

A table of listeners, with corresponding adapters and listener methods, is available at http://java.sun.com/docs/books/tutorial/uiswing/events/api.html

Location of Listener Code

There are numerous options for where to locate the code for a Listener.

Separate File

Deitel Edition 2, fig 10.12. Note this is AWT, not swing, but the event handling principles are the same.

// Fig. 10.12: MyChoice.java
// Using a Choice button to select a font.
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import com.deitel.jhtp2.ch10.FontNameHandler;

public class MyChoice extends Applet {
   private Choice fonts;
   private TextField t;

   public void init()
   {
      // Create a Choice button and add items to it
      fonts = new Choice();
      fonts.add( "Monospaced" );  // Courier
      fonts.add( "SansSerif" );   // Helvetica
      fonts.add( "Serif" );       // Times

      t = new TextField( fonts.getItem( 0 ), 30 );
      t.setEditable( false );
      t.setFont( new Font( fonts.getItem( 0 ),
         Font.PLAIN, 12 ) );

      fonts.addItemListener( new FontNameHandler( t ) );
      fonts.addItemListener( new SetTextFieldHandler( t ) );

      add( fonts );
      add( t );
   }
}

class SetTextFieldHandler implements ItemListener {
   private TextField field;

   public SetTextFieldHandler( TextField t ) { field = t; }

   public void itemStateChanged( ItemEvent e )
   {
      Choice choice = (Choice) e.getItemSelectable();
         
      field.setText( "Index: " + choice.getSelectedIndex() +
         "; Font: " + e.getItem() );
   }
}

\begin{verbatim}
in one file, and in another file

\begin{verbatim}
// Fig. 10.12: FontNameHandler.java
// Class capable of listening for events from a Choice
// or List object and setting the font on the specified
// Component passed to the constructor.
package com.deitel.jhtp2.ch10;
import java.awt.*;
import java.awt.event.*;

public class FontNameHandler implements ItemListener {
   private Component component;

   public FontNameHandler( Component c ) { component = c; }

   public void itemStateChanged( ItemEvent e )
   {
      component.setFont( new Font( e.getItem().toString(),
         component.getFont().getStyle(), 
         component.getFont().getSize() ) );
   }
}

Same File, Separate Class

Deitel Edition 2, fig 10.8. Note this is AWT, not swing, but the event handling principles are the same.

// Fig. 10.8: MyButtons.java
// Creating push buttons.
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;

public class MyButtons extends Applet
{
   private Button pushButton1, pushButton2;

   public void init()
   {
      // create buttons
      pushButton1 = new Button( "Button 1" );
      pushButton1.addActionListener(
         new Button1Handler( this ) );
      add( pushButton1 );

      pushButton2 = new Button( "Button 2" );
      pushButton2.addActionListener(
         new Button2Handler( this ) );
      add( pushButton2 );
   }
}

class Button1Handler implements ActionListener
{
   Applet applet;

   public Button1Handler( Applet a ) { applet = a; }

   public void actionPerformed( ActionEvent e )
   {
      applet.showStatus( "You pressed: " +
         e.getActionCommand() );
   }
}

class Button2Handler implements ActionListener
{
   Applet applet;

   public Button2Handler( Applet a ) { applet = a; }

   public void actionPerformed( ActionEvent e )
   {
      applet.showStatus( "You pressed: " +
         e.paramString() );
   }
}

Note that the public class MyButtons does not claim to implement any interface, but the two non-public classes Button1Handler and Button2Handler each claim to implement the ActionListener interface, which means they must contain a

public void actionPerformed ( ActionEvent ... )
method. The link between the action event generators (pushButton1 and pushButton2 in MyButtons and the handlers is done with the addActionListener( ... ) methods of the event generators, in this case the handler objects have no identifier names assigned and are therefore "anonymous".

In this example, there are two handler objects. When a handler is instantiated with new ( ... ), its constructor is passed a reference (an internal identifier known to the Java run-time system), which in this case identifies an applet object. This value is stored inside the handler object by the constructor and is used by the actionPerformed method to write on the status line of the associated applet. Even an anonymous object has an internal identifier (32 bit number) known to the Java runtime system, even if we don't have any way to refer to the object, as here.

Same File, Same Class, As Method

Deitel fig 12.26

// Fig. 12.26: GridLayoutDemo.java
// Demonstrating GridLayout.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class GridLayoutDemo extends JFrame
                            implements ActionListener {
   private JButton b[];
   private String names[] =
      { "one", "two", "three", "four", "five", "six" };
   private boolean toggle = true;
   private Container c;
   private GridLayout grid1, grid2;

   public GridLayoutDemo()
   {
      super( "GridLayout Demo" );

      grid1 = new GridLayout( 2, 3, 5, 5 );
      grid2 = new GridLayout( 3, 2 );

      c = getContentPane();
      c.setLayout( grid1 );

      // create and add buttons
      b = new JButton[ names.length ];

      for (int i = 0; i < names.length; i++ ) {
         b[ i ] = new JButton( names[ i ] );
         b[ i ].addActionListener( this );
         c.add( b[ i ] );
      }

      setSize( 300, 150 );
      show();
   }

   public void actionPerformed( ActionEvent e )
   { 
      if ( toggle ) c.setLayout( grid2 );
      else
         c.setLayout( grid1 );

      toggle = !toggle;
      c.validate();
   }

   public static void main( String args[] )
   {
      GridLayoutDemo app = new GridLayoutDemo();

      app.addWindowListener(
         new WindowAdapter() {
            public void windowClosing( WindowEvent e )
            {
               System.exit( 0 );
            }
         }
      );
   } 
}

Same File, Same Class, As Anonymous Handler

Deitel fig 12.11

// Fig. 12.11: CheckBoxTest.java
// Creating Checkbox buttons.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class CheckBoxTest extends JFrame {
   private JTextField t;
   private JCheckBox bold, italic;

   public CheckBoxTest()
   {
      super( "JCheckBox Test" );

      Container c = getContentPane();
      c.setLayout(new FlowLayout());

      t = new JTextField( "Watch the font style change", 20 );
      t.setFont( new Font( "TimesRoman", Font.PLAIN, 14 ) );
      c.add( t );

      // create checkbox objects
      bold = new JCheckBox( "Bold" );
      c.add( bold );     

      italic = new JCheckBox( "Italic" );
      c.add( italic );

      CheckBoxHandler handler = new CheckBoxHandler();
      bold.addItemListener( handler );
      italic.addItemListener( handler );

      setSize( 275, 100 );
      show();
   }

   public static void main( String args[] )
   { 
      CheckBoxTest app = new CheckBoxTest();

      app.addWindowListener(
         new WindowAdapter() {
            public void windowClosing( WindowEvent e )
            {
               System.exit( 0 );
            }
         }
      );
   }

   private class CheckBoxHandler implements ItemListener {
      private int valBold = Font.PLAIN;
      private int valItalic = Font.PLAIN;

      public void itemStateChanged( ItemEvent e )
      {
         if ( e.getSource() == bold )
            if ( e.getStateChange() == ItemEvent.SELECTED )
               valBold = Font.BOLD;
            else
               valBold = Font.PLAIN;
               
         if ( e.getSource() == italic )
            if ( e.getStateChange() == ItemEvent.SELECTED )
               valItalic = Font.ITALIC;
            else
               valItalic = Font.PLAIN;

         t.setFont(
            new Font( "TimesRoman", valBold + valItalic, 14 ) );
         t.repaint();
      }
   }
}

Same File, Same Class, As Inner Class

Deitel fig 12.7

// Fig. 12.7: TextFieldTest.java
// Demonstrating the JTextField class.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class TextFieldTest extends JFrame {
   private JTextField text1, text2, text3;
   private JPasswordField password;

   public TextFieldTest()
   {
      super( "Testing JTextField and JPasswordField" );

      Container c = getContentPane();
      c.setLayout( new FlowLayout() );

      // construct textfield with default sizing
      text1 = new JTextField( 10 );
      c.add( text1 );

      // construct textfield with default text
      text2 = new JTextField( "Enter text here" );
      c.add( text2 );

      // construct textfield with default text and
      // 20 visible elements and no event handler
      text3 = new JTextField( "Uneditable text field", 20 );
      text3.setEditable( false );
      c.add( text3 );

      // construct textfield with default text
      password = new JPasswordField( "Hidden text" );
      c.add( password );

      TextFieldHandler handler = new TextFieldHandler();
      text1.addActionListener( handler );
      text2.addActionListener( handler );
      text3.addActionListener( handler );
      password.addActionListener( handler );

      setSize( 325, 100 );
      show();
   }

   public static void main( String args[] )
   { 
      TextFieldTest app = new TextFieldTest();

      app.addWindowListener(
         new WindowAdapter() {
            public void windowClosing( WindowEvent e )
            {
               System.exit( 0 );
            }
         }
      );
   }

   // inner class for event handling
   private class TextFieldHandler implements ActionListener {
      public void actionPerformed( ActionEvent e )
      {
         String s = "";

         if ( e.getSource() == text1 )
            s = "text1: " + e.getActionCommand();
         else if ( e.getSource() == text2 )
            s = "text2: " + e.getActionCommand();
         else if ( e.getSource() == text3 )
            s = "text3: " + e.getActionCommand();
         else if ( e.getSource() == password ) {
            JPasswordField pwd =
               (JPasswordField) e.getSource();
            s = "password: " +
                new String( pwd.getPassword() );
         }

         JOptionPane.showMessageDialog( null, s );
      }
   }   
}

Examples

Deitel figure 12.10 provides examples of JButtons

// Fig. 12.10: ButtonTest.java
// Creating JButtons.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class ButtonTest extends JFrame {
   private JButton plainButton, fancyButton;

   public ButtonTest()
   {
      super( "Testing Buttons" );

      Container c = getContentPane();
      c.setLayout( new FlowLayout() );

      // create buttons
      plainButton = new JButton( "Plain Button" );
      c.add( plainButton );

      Icon bug1 = new ImageIcon( "bug1.gif" );
      Icon bug2 = new ImageIcon( "bug2.gif" );
      fancyButton = new JButton( "Fancy Button", bug1 );
      fancyButton.setRolloverIcon( bug2 );
      c.add( fancyButton );

      // create an instance of inner class ButtonHandler
      // to use for button event handling 
      ButtonHandler handler = new ButtonHandler();
      fancyButton.addActionListener( handler );
      plainButton.addActionListener( handler );

      setSize( 275, 100 );
      show();
   }

   public static void main( String args[] )
   { 
      ButtonTest app = new ButtonTest();

      app.addWindowListener(
         new WindowAdapter() {
            public void windowClosing( WindowEvent e )
            {
               System.exit( 0 );
            }
         }
      );
   }

   // inner class for button event handling
   private class ButtonHandler implements ActionListener {
      public void actionPerformed( ActionEvent e )
      {
         JOptionPane.showMessageDialog( null,
            "You pressed: " + e.getActionCommand() );
      }
   }
}

Another example of an applet which implements an ActionListener interface is Beeper.java, which is available at http://java.sun.com/docs/books/tutorial/ui/components/example-1dot1/Beeper.java

/*
* 1.1 version.
*/

import java.applet.Applet;
import java.awt.Button;
import java.awt.Toolkit;
import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class Beeper extends Applet implements ActionListener
{
    Button button;

    public void init()
    {
        setLayout(new BorderLayout());
        button = new Button("Click Me");
        add("Center", button);

        button.addActionListener(this);
    }

    public void actionPerformed(ActionEvent e)
    {
            Toolkit.getDefaultToolkit().beep();
    }
}

The following example shows a public class which implements more than one Listener interface (Deitel figure 12.17).

// Fig. 12.17: MouseTracker.java
// Demonstrating mouse events.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class MouseTracker extends JFrame
             implements MouseListener, MouseMotionListener {
   private JLabel statusBar;

   public MouseTracker()
   {
      super( "Demonstrating Mouse Events" );

      statusBar = new JLabel();
      getContentPane().add( statusBar, BorderLayout.SOUTH );
    
      // application listens to its own mouse events
      addMouseListener( this );
      addMouseMotionListener( this );

      setSize( 275, 100 );
      show();
   }

   // MouseListener event handlers
   public void mouseClicked( MouseEvent e )
   {
      statusBar.setText( "Clicked at [" + e.getX() +
                         ", " + e.getY() + "]" );
   }

   public void mousePressed( MouseEvent e )
   {
      statusBar.setText( "Pressed at [" + e.getX() +
                         ", " + e.getY() + "]" );
   }

   public void mouseReleased( MouseEvent e )
   {
      statusBar.setText( "Released at [" + e.getX() +
                         ", " + e.getY() + "]" );
   }

   public void mouseEntered( MouseEvent e )
   {
      statusBar.setText( "Mouse in window" );
   }

   public void mouseExited( MouseEvent e )
   {
      statusBar.setText( "Mouse outside window" );
   }

   // MouseMotionListener event handlers
   public void mouseDragged( MouseEvent e )
   {
      statusBar.setText( "Dragged at [" + e.getX() +
                         ", " + e.getY() + "]" );
   }

   public void mouseMoved( MouseEvent e )
   {
      statusBar.setText( "Moved at [" + e.getX() +
                         ", " + e.getY() + "]" );
   }

   public static void main( String args[] )
   { 
      MouseTracker app = new MouseTracker();

      app.addWindowListener(
         new WindowAdapter() {
            public void windowClosing( WindowEvent e )
            {
               System.exit( 0 );
            }
         }
      );
   }
}

Adapter Classes

See Deitel E3 section 12.12.

To implement an interface it is necessary to explicitly implement each of the methods described in the interface, even it the method does nothing (i.e. the body is an empty pair of curly braces). To ease the writing of such classes, Java provides ``adapter'' classes, which implement an interface with empty methods. In practice, if you wanted to implement only a few of the available methods in an interface, you would probably subclass an adapter class and override its methods with your version of the methods which you want to really do something. Interfaces involving a mouse or keyboard or window are the ones most likely to be used in this way.

An example is Deitel E3 fig 12.19, where the mouseDragged ( ... ) handler is wanted but not the other mouse motion handler ( mouseMoved ), and only windowClosing ( ... ) of the seven methods associated with a WindowListener is wanted.

// Fig. 12.19: Painter.java
// Using class MouseMotionAdapter.
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;

public class Painter extends JFrame {
   private int xValue = -10, yValue = -10;

   public Painter()
   {
      super( "A simple paint program" );

      getContentPane().add(
         new Label( "Drag the mouse to draw" ),
         BorderLayout.SOUTH );

      addMouseMotionListener(
         new MouseMotionAdapter() {
            public void mouseDragged( MouseEvent e )
            {
               xValue = e.getX();
               yValue = e.getY();
               repaint();
            }           
         }
      );

      setSize( 300, 150 );  
      show();   
   }

   public void paint( Graphics g )
   {
      g.fillOval( xValue, yValue, 4, 4 );
   }

   public static void main( String args[] )
   {
      Painter app = new Painter();

      app.addWindowListener(
         new WindowAdapter() {
            public void windowClosing( WindowEvent e )
            {
               System.exit( 0 );
            }
         }
      );
   }
}

A table of Listeners and Adapter Classes is available at http://java.sun.com/docs/books/tutorial/uiswing/events/api.html

Further Reading

Read Deitel chapters 12 and 13 on GUI components. There are many on-line tutorials on the Internet about Java GUIs (be sure they cover version 1.1 and later; version 1.0 used a different model).

Javasoft has "Writing Event Listeners" at http://java.sun.com/docs/books/tutorial/uiswing/events/index.html including ``How to Write an Action Listener'' at http://java.sun.com/docs/books/tutorial/uiswing/events/actionlistener.html and ``How to Write an Item Listener'' at http://java.sun.com/docs/books/tutorial/uiswing/events/itemlistener.html

Objectives

After succesful completion, the student will be able to demonstrate knowledge of:

About this document ...

Event Handling in Java

This document was generated using the LaTeX2HTML translator Version 96.1 (Feb 5, 1996) Copyright � 1993, 1994, 1995, 1996, Nikos Drakos, Computer Based Learning Unit, University of Leeds.

The command line arguments were:
latex2html -split 0 events.

The translation was initiated by Selwyn Russell on Tue Feb 29 17:23:19 EST 2000


Selwyn Russell
Tue Feb 29 17:23:19 EST 2000
Hosted by www.Geocities.ws

1