Composing Events with Event Accumulators

Event accumulators capture two or more events that occur within a specified maximum amount of time of each other, and combine them into a composite event that is dispatched to interested clients. Event accumulators can be used to overcome the event dispatching limitations of some user interface components.

1. Introduction

Event accumulators capture two or more events that occur within a specified maximum amount of time of each other, and combine them into a composite event that is dispatched to interested clients. Event accumulators can be used to overcome the event dispatching limitations of some user interface components.

2. An Example Event Accumulator

One of the functions of the Java Swing JEditorPane class is to render HTML (Geary 1999). When the user clicks on a hyperlink, JEditorPane objects fire an event that notifies listeners that the user has activated a hyperlink, and supplies the listener with the URL of the hyperlink.

The standard behavior of applications that display hyperlinks is that clicking on the hyperlink with the left mouse button invokes some application dependent behavior, such as displaying the information that the hyperlink points to. Developers might want to perform a different kind of action when the right mouse button is clicked, such as invoking a context sensitive menu. The mouse event that causes a JEditorPane to fire a hyperlink event is not sent to the listeners. A listener cannot determine whether the user clicked the left or right mouse button over the hyperlink.

The Component class fires mouse click events when the mouse is clicked inside its bounding box. As a sub-class of the Component class, the JEditorPane class fires mouse click events as well as hyperlink events. In fact, JEditorPane objects listen for these mouse click events to determine when the user has clicked on a hyperlink.

An obvious first attempt to determine whether the left or right mouse button was clicked would be to listen for the mouse click event that triggered the hyperlink event: if there is a mouse click event followed by a hyperlink event, the mouse click event must have initiated the hyperlink event, and the mouse click event can be examined to determine which button was clicked. However, the order in which events arrive is non-deterministic. Because events can arrive in any order, clients need to handle two cases: if the hyperlink event arrives first, clients need to listen for a mouse event; if the mouse event arrives first, clients need to listen for the hyperlink event. Event accumulators solve this by listening for two or more events that occur within a specified maximum amount of time of each other, and combining them into a composite event that is dispatched to interested clients. The composite event provides all the information about the captured events.

3. Implementation

In the example below, the EventAccumulator class implements the HyperlinkListener and MouseListener interfaces, and is added to the JEditorPane object as a hyperlink listener and as a mouse listener. When the EventAccumulator object receives a mouse click event it starts a thread that sleeps for 100 milliseconds. If, by the time the thread wakes, the EventAccumulator has received a hyperlink event, the EventAccumulator fires a composite event that contains the hyperlink and mouse events. Similarly, when the EventAccumulator object receives a hyperlink event, it starts a thread that sleeps for 100 milliseconds. If, by the time the thread wakes, the EventAccumulator has received a mouse click event, the EventAccumulator fires the composite event.

Event accumulator class diagram

References

  • Geary, D. M., Graphic Java 2 Mastering the JFC, Volume II: Swing, 3rd edition, Prentice-Hall, 1999.