Procedural Vs Event Driven Programming

Procedural programs have a single order of execution. User interaction takes place when the program is ready for it.

Event driven programs do not have a single order of execution. The order of execution depends on the events, normally user interactions such as selecting a menu item, pressing a button, etc.

Graphical User Interface (GUI) models require an event approach.

The operating system registers the events and sends them to the application, say Java Virtual Machine. Java maintains the current event queue and processing events from it.


Low-level vs. Semantic Events

The AWT provides two conceptual types of events: low-level and semantic.

A low-level event is one which represents a low-level input or window-system occurrence on a visual component on the screen.

For example, a low level event is a key press or a key release, a mouse click, drag, move, or release, and so on.

The low-level event classes defined by the AWT are as follows:

java.util.EventObject
java.awt.AWTEvent 
   java.awt.event.ComponentEvent 
     (component resized, moved, etc.)
   java.awt.event.FocusEvent 
     (component got focus, lost focus)
   java.awt.event.InputEvent
      java.awt.event.KeyEvent 
       (component got key-press,key-release, etc.)
      java.awt.event.MouseEvent 
       (component got mouse-down, mouse-move, etc.)
   java.awt.event.ContainerEvent
   java.awt.event.WindowEvent

Semantic events are defined at a higher-level to encapsulate the semantics (meaning) of a user interface component's model.

For example,

The semantic event classes defined by the AWT are as follows:

java.util.EventObject
   java.awt.AWTEvent
      java.awt.event.ActionEvent ("do a command")
      java.awt.event.AdjustmentEvent 
        ("value was adjusted")
      java.awt.event.ItemEvent 
        ("item state has changed")
      java.awt.event.TextEvent 
        ("the value of the text object changed")


Note that these semantic events are not tied to specific screen-based component classes, but may apply across a set of components which implement a similar semantic model.

Example,

Case-1


Case-2



Delegation Event Model in Java

An event is propagated from a "Source" object to a "Listener" object by

invoking a method on the listener and passing in the instance of the event subclass which defines the event type generated.

An Event Source is an object which originates or "fires" events. The source defines the set of events it emits by providing a set of methods which are used to register specific listeners for those events.

A Listener is an object that implements a specific EventListener interface.

An EventListener interface defines one or more methods which are to be invoked by the event source in response to each specific event type handled by the interface.

In an AWT program, the event source is typically a GUI component and the listener is commonly an object (or "adapter", discussed later) which implements the appropriate listener (or set of listeners) in order for an application to control the flow/handling of events.


Simple Examples

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

public class simpleEvent1 extends Applet                  
{
    Button  b1;
    
    // One-time initialization for the applet
    public void init() {
    
              b1 = new Button("First Button");
              this.add(b1);

          // creates one object for button listener
          MyButtonListener listB1 = new  MyButtonListener();

          // adds listB1 as the button listener
          b1.addActionListener(listB1);
    }

    // Draw the applet whenever necessary.
    public void paint(Graphics g) {
        // The pink oval
        g.setColor(Color.yellow);
        g.fillOval(10, 50, 330, 100);
    }
}

// Defines new class for ActionListener interface, which can be used for buttons and some other GUI componenets
class MyButtonListener  implements ActionListener
{
    public void actionPerformed(ActionEvent event) {

         String  tmpString = event.getActionCommand();
         System.out.println("Button Pressed: " +  tmpString);

    }
}
 




Processing Events

The Java runtime passes the event to the corresponding component's processEvent() method:

protected void processEvent(AWTEvent e)

The processEvent() method determines the type of the event and passes it on to one of five other methods in the Component class:

void processComponentEvent(ComponentEvent e)
void processFocusEvent(FocusEvent e)
void processKeyEvent(KeyEvent e)
void processMouseEvent(MouseEvent e)
void processMouseMotionEvent(MouseEvent e)

(note that all the above methods are protected)


EventListeners

We can register an event listener for the event type with the component.

Typically, an event listener would perform the required action for the corresponding event (user interaction).

For example, an event listener for a mouse event must implement methods for mouse pressed, released, dragged, etc.

An even listener is an object of the corresponding event listener interface.

The low-level listener interfaces defined by the AWT are as follows:

The semantic listener interfaces defined by the AWT are as follows:

For example,

MouseListener declares these methods,

 public abstract void mouseClicked(MouseEvent e)
 public abstract void mousePressed(MouseEvent e)
 public abstract void mouseReleased(MouseEvent e)
 public abstract void mouseEntered(MouseEvent e)
 public abstract void mouseExited(MouseEvent e)

When a component receives a MouseEvent, its processMouseEvent() method checks the ID of the MouseEvent to determine whether this is a

mouse pressed, mouse released, mouse entered, or mouse exited event.

Then it calls the corresponding method in each registered MouseListener object.

Example,

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

public class simpleMouseEvent1 extends Applet
{

    // One-time initialization for the applet
    public void init() {
        
        MyMouseListener ml = new MyMouseListener();
          // adds mouse listener to 'this' applet
        this.addMouseListener(ml);
    }
    
    // Draw the applet whenever necessary.  
    public void paint(Graphics g) {

        g.setColor(Color.pink);
        g.fillOval(10, 50, 330, 100);
    }
}


class MyMouseListener implements MouseListener
{
    

   public void mousePressed(MouseEvent e) {   
       System.out.println("Mouse pressed at: " + e.getX() + " " + e.getY());
   }
 
   // We must implement these methods, 
   // but they don't need to do anything.

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

}




Inner Classes

Inner classes allows classes to be defined in any scope.

In previous releases, Java supported only top-level classes, which must be members of packages.

In JDK1.1 release, the programmer can now define inner classes as members of other classes,

Inner classes are normally useful to support the work of the class in which they nest.

Here is an incomplete class FixedStack which implements a stack, and is willing to enumerate the elements of the stack, from the top down:

     public class FixedStack {
         Object array[];
         int top = 0;
         FixedStack(int fixedSizeLimit) {
             array = new Object[fixedSizeLimit];
         }
     
         public void push(Object item) {
             array[top++] = item;
         }
         public boolean isEmpty() {
             return top == 0;
         }
         // other stack methods go here...
     
         /** This adapter class is defined as part of its target class,
          *  It is placed alongside the variables it needs to access.
          */
         class Enumerator implements java.util.Enumeration {
             int count = top;
             public boolean hasMoreElements() {
                 return count > 0;
              }
             public Object nextElement() {
                 if (count == 0)
                     throw new NoSuchElementException("FixedStack");
                 return array[--count];
               }
             }

         public java.util.Enumeration elements() {
             return new Enumerator();
         }
     }

An inner class name is qualified by its enclosing class. In the above example, the proper name of Enumerator is FixedStack.Enumerator.

In Java, a class's non-static members are able to refer to each other, and they all take their meaning relative to the current instance this.

Thus, the instance variable array of FixedStack is available to the instance method push and to the entire body of the inner class FixedStack.Enumerator.

Just as instance method bodies "know" their current instance this, the code within any inner class like Enumerator "knows" its enclosing instance, the instance of the enclosing class from which variables like array are fetched.

For more examples, see the online documentation for JDK1.1.



Anonymous classes

JDK 1.1 allows an abbreviated notation for local objects.

A single expression syntax combines the definition of an anonymous class with the allocation of the instance:

For example,

         Enumeration myEnumerate(final Object array[]) {

             return new Enumeration() {
                 int count = 0;
                 public boolean hasMoreElements()
                     { return count < array.length; }
                 public Object nextElement()
                     { return array[count++]; }
             };

         } 

For example,

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

public class simpleEvent3 extends Applet          
{
    Button  b1;
    
    // One-time initialization for the applet
    public void init() {
    
        b1 = new Button("First Button");
        this.add(b1);
      
        b1.addActionListener(
            new ActionListener() {
               public void actionPerformed(ActionEvent e) {
                  System.out.println("First Button Pressed");           
               }            
            }
          );
       }


    // Draw the applet whenever necessary.
    public void paint(Graphics g) {
        // The pink oval
        g.setColor(Color.yellow);
        g.fillOval(10, 50, 330, 100);       
     }    
}

Adapter Classes

The AWT provides a number of adapter classes for the different EventListener interfaces. These are:


Each adapter class implements the corresponding interface with a series of do-nothing methods. For example, MouseListener declares these five methods:

 public abstract void mouseClicked(MouseEvent e)
 public abstract void mousePressed(MouseEvent e)
 public abstract void mouseReleased(MouseEvent e)
 public abstract void mouseEntered(MouseEvent e)
 public abstract void mouseExited(MouseEvent e)

Therefore, MouseAdapter looks like this:


By subclassing MouseAdapter rather than implementing MouseListener directly, you can avoid having to write the methods you don't actually need. You only override those that you plan to actually implement.

For example, here's a MouseAdapter that beeps when the mouse is clicked


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


public class MouseBeeper extends MouseAdapter  {

  public void mouseClicked(MouseEvent e) {
    Toolkit.getDefaultToolkit().beep();
  }

}


Without extending the MouseAdpter class, we need to write the same class like this

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


public class MouseBeeper implements MouseListener  {

  public void mouseClicked(MouseEvent e) {
    Toolkit.getDefaultToolkit().beep();
  }

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

}

Another Example,


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


public class simpleMouseEvent3 extends Applet
{

    // One-time initialization for the applet
    public void init() {
 
            this.addMouseListener(
                 new MouseAdapter() {
                      public void mousePressed(MouseEvent e) { 
                          System.out.println("Mouse pressed at: " + e.getX() + " " + e.getY());
                       } 
                   }
              );
       }
 

    // Draw the applet whenever necessary.  Do some fancy graphics.
    public void paint(Graphics g) {
        g.setColor(Color.pink);
        g.fillOval(10, 50, 330, 100);
    }

}