3.5. Events and Listeners

When a user does something, such as clicks a button or selects an item, the application needs to know about it. Many Java-based user interface frameworks follow the Observer design pattern to communicate user input to the application logic. So does IT Mill Toolkit. The design pattern involves two kinds of elements: an object and a number of observers that listen for events regarding the object. When an event related to the object occurs, the observers receive a notification regarding the event. In most cases there is only one observer, defined in the application logic, but the pattern allows for multiple observers. As in the event-listener framework of Java SE, we call the observing objects listeners.

In the ancient times of C programming, callback functions filled largely the same need as listeners do now. In object-oriented languages, we have only classes and methods, not functions, so the application has to give a class interface instead of a callback function pointer to the framework. However, IT Mill Toolkit supports defining a method as a listener as well.

Events can serve many kinds of purposes. In IT Mill Toolkit, the usual purpose of events is handling user interaction in a user interface. Session management can require special events, such as time-out, in which case the event is actually the lack of user interaction. Time-out is a special case of timed or scheduled events, where an event occurs at a specific date and time or when a set time has passed. Database and other asynchronous communications can cause events too.

To receive events of a particular type, an application must include a class that implements the corresponding listener interface. In small applications, the application class itself could implement the needed listener interfaces. Listeners are managed by the AbstractComponent class, the base class of all user interface components. This means that events regarding any component can listened to. The listeners are registered in the components with addListener() method.

Most components that have related events define their own event class and corresponding listener classes. For example, the Button has Button.ClickEvent events, which can be listened to through the Button.ClickListener interface. This allows an application to listen to many different kinds of events and to distinguish between them at class level. This is usually not enough, as applications usually have many components of the same class and need to distinguish between the particular components too. We will look into that more closely below. The purpose of this sort of class level separation is to avoid having to make type conversions in the handlers.

Notice that many listener interfaces inherit the java.util.EventListener superinterface, but it is not generally necessary to inherit it.

Figure 3.3. Class Diagram of a Button Click Listener

Class Diagram of a Button Click Listener

Figure 3.3, “Class Diagram of a Button Click Listener” illustrates an example where an application-specific class inherits the Button.ClickListener interface to be able to listen for button click events. The application must instantiate the listener class and register it with addListener(). When an event occurs, an event object is instantiated, in this case a ClickEvent. The event object knows the related UI component, in this case the Button.

Section 4.4, “Handling Events with Listeners” goes into details of handling events in practice.