Java listeners and adapters

Understanding and Using the Java Delegation Event Model

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

The Delegation Event model is one of the many techniques used to handle events in GUI (Graphical User Interface) programming languages. GUI represents a system where a user visually or graphically interacts with the system. Other interactive systems are text-based or CUI (Character User Interface). CUI interacts with the system by typing out commands in the console. GUI programming is inherently event-driven, meaning whenever a user initiates an activity (such as a mouse move that changes the coordinates of the mouse pointer in the screen or clicks a button, scrolls a page, and so forth) is deemed an event where the GUI event handler must map the relevant activity to a piece of code that explains what response the application should provide to the user. This is the basis of event handling. This Java programming tutorial is an attempt to explore the idea of event handling in general, and delegation event modeling in particular, with a focus on its implementation in Java.

Check out TechRepublic Academy to learn about Java!

Dele1

Figure 1: GUI components in a frame

Event-driven Programming in Java

Understanding the event-driven programming paradigm is the most important aspect of GUI programming. Java, as a language, provides multipurpose libraries to support almost every need of the programmer. The core libraries for GUI are AWT, Swing, and JavaFX. GUI programs written with these toolkits are naturally event-driven, where the program waits for events to occur and responds to events if and when they occur.

Читайте также:  Html print color backgrounds

Typically, a program is a set of code that is interpreted as an instruction by the CPU after compilation. the execution starts off with some initial data. The objective is to transform a series of computations into the desired output. During the whole process, from the beginning to the end of the execution, the control of the processing sequence hops, loops, and traverses through many conditional paths. The end-user does not have any control during the execution process. One simply initiates a run command and waits for the processing to be done, with absolutely no interactivity in-between the execution and the completion.

Event-driven programming brings a sense of interactivity into the scene. The user provides commands through graphical inputs such as buttons, menus, text boxes, and so on; this breaks the monotony of the contiguous sequence of execution of a typical program. The program now halts to respond to user commands during its execution. The execution path of the program can be manipulated dynamically by the user. This almost gives a human face to an application.

The program that interacted only with the hardware and underlying platform now includes human input as well. The end-user has some say during program execution. This not only opens a new horizon of programming but also opens a Pandora’s box of new complexity.

Graphical interfaces have two sole objectives: looks and interactivity. There is no practical limit to how great an interface may look or how interactive it is, sometimes to the verge of sheer absurdity. Most of today’s software puts a huge effort into the look and feel of its interfaces. Many are so ridiculously handsome that they are 90% looks and only 10% cooks. Guess how many man-hours are invested to code this hypothetical message box developed in the name of looks and interactivity.

Dele2

Figure 2: A sample interface, somewhat overdone

Java Delegation Event Model

Back in the old days, Java used a Chain of Responsibility pattern to process events. For example, when a button is clicked, an event is generated, which then is passed through a chain of components. The chain of components is defined by the hierarchy of classes and interfaces. An event is caught and handled by the handler class. This mechanism was used by Java version 1.0, which is very different from the event handling scheme of Java version 1.1 onwards. Old methods are still supported, but deprecated and hence not recommended for new programs. A modern approach is based on the delegation event model.

The processing model of Java 1.1’s event hierarchy facilitates more than one receiver subscription. The subscriber thus can send notifications to all of them in response to a change or updates. This mechanism reminds one of the Observer Pattern. In the delegation event model, a class designated as an event source generates an event and sends it to one or more listeners. The responsibility of handling the event process is handed over to its listeners. The listener’s classes wait in the vicinity, to spring into action only when it is poked by the event that it is interested in. The design scheme is neatly decoupled from the main application logic that generates the event.

However, the listeners must register or agree with the event source class to receive any notification. This means that a particular event is processed only by a specific listener. The overhead of going through a chain of containment hierarchy of Java 1.0 is eliminated. Java 1.0 used to make events go through many listeners that do not process the particular event, wasting valuable time. The modern approach made the delegation simple, efficient, and effective in view of its decoupled nature and performance issues.

Naming Scheme and Conventions for Java Events

A component can be mapped to numerous types of events; for example, a click event of a button behaves differently than a click event of a list box. It is quite easy to be lost in the event scheme API. However, Java uses a very intuitive naming convention. Related event classes, interfaces, and methods – and their types – can be very easily known by their naming scheme. For example, the listener naming scheme for an event of, say, classMyEvent may be MyEventListener and the consuming event method may be addMyEventListener, removeMyEventListener, and so forth.

Java Delegation: Events, Sources, and Listeners

The delegation event model can be defined by three components: event, event source, and event listeners.

  • Events: The event object defines the change in state in the event source class. For example, interacting with the graphical interfaces, such as clicking a button or entering text via keyboard in a text box, item selection in a list, all represent some sort of change in the state. The event object is used to carry the required information about the state change. However, all events are not caused by user interaction. There are events, such as a timer event, hardware/software events, and so forth, that do not depend upon user interaction. They occur automatically. We can define the procedure to handle them once they occur.
  • Event sources: Event sources are objects that cause the events to occur due to some change in the property of the component. Because there can be various types a component can trigger, each must be registered to a listener to provide a suitable response.
  • Event listeners: Event listeners are objects that are notified as soon as a specific event occurs. Event listeners must define the methods to process the notification they are interested to receive.

Dele3

Figure 3: Java Events, sources, and listeners

Listener Interface and Adapter Classes in Java

in the Java event hierarchy, we can find that some listener interfaces depend on more than one event handler. Among them, only a few of the event handling methods contain any meaningful code. Most are declared as an empty body. These methods are supposed to be defined by their implementing classes. Suppose we want to implement a mouse event: we either can implement some or all of the mouse events by implementing listener interfaces or extend the adapter class and define only the required events that we want to process. Consider the following Java code example showing how to use listener interface and adapter classes:

package org.mano.example1; import java.awt.BorderLayout; import java.awt.Color; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; public class MouseTracker extends JFrame< private static final long serialVersionUID = 1L; private final JPanel trackPanel; private final JLabel statusLabel; public MouseTracker()< super("Mouse Tracker"); trackPanel=new JPanel(); trackPanel.setBackground(Color.BLUE); add(trackPanel, BorderLayout.CENTER); statusLabel=new JLabel(""); add(statusLabel, BorderLayout.NORTH); trackPanel.addMouseListener(new MouseHandler()); trackPanel.addMouseMotionListener(new MouseHandler()); > private class MouseHandler implements MouseListener, MouseMotionListener< @Override public void mouseDragged(MouseEvent e) < // TODO Auto-generated method stub > @Override public void mouseMoved(MouseEvent e) < // TODO Auto-generated method stub > @Override public void mouseClicked(MouseEvent e) < statusLabel.setText(String .format("Clicked at (x=%d, y=%d)", e.getX(), e.getY())); > @Override public void mousePressed(MouseEvent e) < // TODO Auto-generated method stub > @Override public void mouseReleased(MouseEvent e) < // TODO Auto-generated method stub > @Override public void mouseEntered(MouseEvent e) < statusLabel.setText("Mouse in scope"); >@Override public void mouseExited(MouseEvent e) < statusLabel.setText("Mouse out of scope"); >> public static void main(String[] args)< MouseTracker mt=new MouseTracker(); mt.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); mt.setSize(400,300); mt.setVisible(true) > >

Listing 1: Mouse event handling with listener interface

Adapter classes implement the corresponding listener interface. For example, the WindowAdapter class implements WindowListener, which is a listener interface for listening to window events such as closing, activated, opened, and so on, events. Similarly, the MouseAdapter class implements MouseListener. The event methods are all derived from the listener interfaces, but the corresponding adapter classes do not provide any body of the event method. These adapter classes are designated as abstract and are meant to be extended. The class that extends defines one or more of the methods to contain the logic of the event handling process. The adapter classes follow the Adapter pattern. However, not all listeners have their corresponding adapter classes in the Java API.

package org.mano.example1; import java.awt.BorderLayout; import java.awt.Color; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; public class MouseTracker2 extends JFrame< private static final long serialVersionUID = 1L; private final JPanel trackPanel; private final JLabel statusLabel; public MouseTracker2()< super("Mouse Tracker"); trackPanel=new JPanel(); trackPanel.setBackground(Color.GREEN); add(trackPanel, BorderLayout.CENTER); statusLabel=new JLabel(""); add(statusLabel, BorderLayout.NORTH); trackPanel.addMouseListener(new MouseHandler()); trackPanel.addMouseMotionListener(new MouseHandler()); > private class MouseHandler extends MouseAdapter< @Override public void mouseClicked(MouseEvent e) < statusLabel.setText(String .format("Clicked at (x=%d, y=%d)", e.getX(), e.getY())); > @Override public void mouseEntered(MouseEvent e) < statusLabel.setText("Mouse in scope"); >@Override public void mouseExited(MouseEvent e) < statusLabel.setText("Mouse out of scope"); >> public static void main(String[] args)< MouseTracker2 mt=new MouseTracker2(); mt.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); mt.setSize(400,300); mt.setVisible(true); > >

Listing 2: Mouse event handling with adapter class

Conclusion to Understanding the Java Delegation Event Model

The idea behind the delegation event model is pretty simple: implement an appropriate interface in the listener to receive the event and register it to the code for event notification. Because there are numerous types of events, each must be separately registered to an appropriate listener. The adapter classes simplify event implementation under certain situations, such as when we need to handle only some of the events that are handled by a particular event listener interface. The major APIs related to events in Java are contained in the java.awt.event, java.awt, and java.util packages. Refer to the Java API documentation for specific details on them.

Источник

Оцените статью