Saturday, 4 August 2012

GUI - Event Handling

GUIs generate events when we interact with GUI. For example, clicking a button, moving the mouse, closing Window etc. Both AWT and swing components generate events.
In java, events are represented by Objects. These objects tell us about event and its source. Examples are: ActionEvent (Clicking a button), WindowEvent (Doing something with window e.g. closing, minimizing). Some event classes of java.awt.event are shown in diagram below:

Event Handling Model
In Java both AWT and Swing components use Event Delegation Model. In this model, processing of an event is delegated to a particular object (handlers) in the program.
It’s a Publish-Subscribe model. That is, event generating component publish an event and event handling components subscribe for that event. The publisher sends these events to subscribers (Similar to the way that we subscribe for newspaper and get the newspaper at home from the publisher). This model separates UI code from program logic, it means that we can create separate classes for UI components and event handlers and hence business/program logic is separated from GUI components.
For a programmer, the event Handling is a three step process in terms of code
  • Create components which can generate events (Event Generators).
  • Build component (objects) that can handle events (Event Handlers).
  • Register handlers with generators.

Event Handling Process
1) Event Generators

The first step is to create an event generator. Most of GUI components can be created by calling their constructors. For example

JButton b1 = new JButton(“Hello”);

Now b1 can generate events.

2) Event Handlers/ Event Listener

The second step is to build components that can handle events.
By Implementing Listener Interfaces - Java defines interfaces for every event type. If a class needs to handle an event, it needs to implement the corresponding listener interface.
To handle “ActionEvent” a class needs to implement “ActionListener”.
To handle “KeyEvent” a class needs to implement “KeyListener”.
To handle “MouseEvent” class needs to implement “MouseListener” and so on.
Package java.awt.event contains different event Listener Interfaces which are shown below:

Lets see example of Listener, the way defined in JDK by Sun:

public interface ActionListener {
        public void actionPerformed(ActionEvent e);
public interface ItemListener {
        public void itemStateChanged(ItemEvent e);

By implementing an interface the class agrees to implement all the methods that are present in that interface. Inside the method the class can do whatever it wants to do with that event. Event Generator and Event Handler can be the same or different classes. 
To handle events generated by Button, a class needs to implement ActionListener interface and thus needs to provide the definition of actionPerformed() method which is present in this interface. 

3) Registering Handler with Generator

The event generator is told about the object which can handle its events. Event Generators have a method addXXXListener(_reference to the object of Handler class_). For example, if b1 is JButton then


Event Handling Process Behind the Scenes
The different participants of Event Handling Process are:

Event Generator / Source
  • Swing and awt components
  • For example, JButton, JTextField, JFrame etc
  • Generates an event object
  • Registers listeners with itself
Event Object 
  • Encapsulate information about event that occurred and the source of that event
  • For example, on clicking a button, ActionEvent object is created.
Event Listener/handler 
  • Receives event objects when notified, then responds
  • Each event source can have multiple listeners registered on it
  • Receives an event whenever one is generated
  • Looks for the listener/handler of that event 
  • If exist, delegate it for processing If not, discard the event.

When button generates an ActionEvent it is sent to JVM which puts it in an event queue. After that when JVM find it appropriate, it de-queue the event object and send it to all the listeners that are registered with that button. This is all shown in the pictorial form above.

Adapter Classes
Till now we have seen that handler class need to implement interface therefore it has to provide definitions of all the methods inside that interface. 
Let us assume that an interface has 10 methods, thus hander class has to provide definitions of all these 10 methods. Even if the requirement is for one method, it has to provide empty definitions of the remaining 9 methods. This is quite irritating for a programmer and here comes the use of Adapter classes.

For listener interfaces containing more than one event handling methods, jdk defines adapter classes. Examples are:
For WindowListener – WindowAdapter,
for MouseMotionListener - MouseMotionAdapter and many more.

Adapter classes provide definitions for all the methods (empty bodies) of their corresponding Listener interface. It means that WindowAdapter class implements WindowListener interface and provide the definition of all methods inside that Listener interface. Consider the following example of MouseMotionAdapter and its corresponding MouseMotionListener interface:

public interface MouseMotionListener {
    public void mouseDragged (MouseEvent me);
    public void mouseMoved (MouseEvent me);
public class MouseMotionAdapter implements MouseMotionListener{
      public void mouseDragged (MouseEvent me) {  }  
      public void mouseMoved (MouseEvent me)   {  }
Now our handler class will inherit from adapter class. Due to inheritance, all the methods of the  adapter class will be  available inside our handler class since adapter classes has already provided definitions with empty bodies. We do not have to provide implementations of all the methods again. We only need to override our method of interest.

public class EventsEx extends MouseMotionAdapter{...}

No comments:

Post a Comment