Concepts / Action Events and Listeners

Action Events and Listeners

Event-oriented programming lets classes communicate by having one class emit events that other classes listen for and respond to.

  • Programming

A Display That Other Parts React To

By this point you have worked with mouse events, key events, and action events. Those are only a few of the event types Java programs use. This article looks at the event mechanism from a different angle than the one you have seen so far. Instead of asking how a single event is handled, it asks how events let separate classes cooperate while staying independent of one another.

Imagine a program made of several classes. One class does the heavy work, and other classes need to display or respond to what that work is doing. The natural first guess is that the working class must somehow call methods on the classes that need the information. The Mandelbrot Viewer program is built so that this does not happen. Its MandelbrotDisplay class does the computation, yet other parts of the program clearly react to what the display is doing. The rest of this article explains how that is possible and why the design is worth learning.

Tracing One Computation Through the Viewer

Follow what happens when the user asks the viewer to compute a new image. The MandelbrotDisplay object begins a computation. At that moment it announces that a computation has started. It does not decide what the rest of the program should do about that fact. Some menus in the Menus class are disabled while the computation runs. The display never reaches into the Menus class to switch them off. The Menus class sets up a listener to hear the announcement, and the listener is the piece that acts.

MandelbrotDisplayemitterMandelbrotPanellistenerMenuslistenersize changed eventcomputation started event
In what order do the emitter and each listener act when something happens, and who calls whom?

Read the diagram as a chain of hand-offs rather than a chain of commands. The arrows show announcements leaving the display. The display does not know which listener will receive each announcement, what that listener will do with it, or whether any listener exists at all. The figure is a simplified picture of a flow the source describes in prose, and the prose is the authoritative description.

Emitters, Listeners, and Events

Definition

Event-oriented programming lets classes communicate by having one class emit events that other classes listen for and respond to. The class that emits events is the emitter. A class that sets up a listener to hear those events and respond is a listener.

In the Mandelbrot Viewer, the MandelbrotDisplay object emits events of various types when various things happen. Two examples the source gives are a change in the size of the display and the start or completion of a computation of an image. The MandelbrotPanel and Menus objects set up listeners to hear those events. The MandelbrotPanel responds to a size change by showing the new display size in its status bar. The Menus class responds to the start and completion of a computation by disabling certain menus and then re-enabling them. In both cases the responding class gets its information from the event itself, not from a method call made by the display.

MandelbrotDisplayemits eventsMandelbrotPanellistensMenuslistenslistens for size eventslistens for computation events
Which classes are emitters, which are listeners, and which connections link them?

Notice the direction of the connection. The listeners depend on the display's events, but the display does not name the listeners. This is the key feature to look for when you read any program description: find the class that announces what happened, then find the classes that were set up to hear the announcement.

Strong Coupling Versus Weak Coupling

Coupling describes the degree to which classes depend on each other. The source defines two kinds. Strong coupling occurs when one class directly calls methods in another class, which makes the two highly dependent. Weak coupling occurs when classes communicate through events or other indirect means, which reduces how much they depend on each other.

The source spells out the alternative the viewer avoids. The display could call methods such as displaySizeChanged() or computationStarted() in the MandelbrotPanel and Menus objects to tell them what is going on. That design would be strong coupling. Any programmer who wanted to use MandelbrotDisplay would then also have to use those two classes, or would have to modify the display so that it no longer refers to them.

MandelbrotDisplayMandelbrotDisplayMandelbrotPanelsize changed eventMandelbrotPaneldirect method callemitsdelivered to listener
How does the dependency structure differ when one class holds a direct reference to another, compared with when it only knows about an event?
QuestionStrong coupling (direct calls)Weak coupling (events)
How does the display talk to the panel?It calls methods on the panel by nameIt emits an event that the panel listens for
What must a reuser also take along?The panel and menus classes it callsNothing beyond the display itself
What happens if the panel is replaced?The display must be changedThe display is unchanged
How much does each class depend on the other?HighlyMuch less

Strong and weak coupling between the display and the classes that respond to it, as described in the source

Reusing the Display in Another Program

The source states the consequence directly. Because events are used for communication, the MandelbrotDisplay class is not strongly coupled to the other classes. It can be used in other programs without any modification and without access to the other classes. Changing or replacing the panel or the menus does not require changing the display, because the display never names them.

Worked example

Identifying emitters and listeners in a weather station program

A small program has a TemperatureSensor class that measures temperature, a DisplayPanel class that shows the latest reading, and an AlarmBox class that sounds when the temperature passes a limit. The sensor announces each new reading as an event. The panel and the alarm each set up a listener. Which class emits events, which classes listen, and does the sensor need to know about the panel?

  1. 1
    Find the announcer

    The sensor announces each new reading, so TemperatureSensor is the emitter.

  2. 2
    Find the listeners

    DisplayPanel and AlarmBox set up listeners to hear the reading event, so both are listeners.

  3. 3
    Check the direction of knowledge

    The panel and the alarm depend on the sensor's event. The sensor does not name either class in its code.

  4. 4
    Test the reuse question

    A different program could use TemperatureSensor with a different panel and no alarm, and the sensor would need no change.

Result

TemperatureSensor emits events; DisplayPanel and AlarmBox listen. The coupling is weak because the sensor never calls methods on its listeners.

When Direct References Are Acceptable

The source is careful not to present events as a cure-all. It says that not everything can be done with events, and that not all strong coupling is bad. The MandelbrotPanel class refers directly to the MandelbrotDisplay class and cannot be used without it. The reasoning is that the whole purpose of a MandelbrotPanel is to hold a MandelbrotDisplay, so the dependency matches the design and causes no problem.

What do you think happens?

If MandelbrotDisplay called methods on MandelbrotPanel and Menus directly, what would a programmer who wants to reuse the display have to do?

Reveal answer
Answer:

The programmer would have to use those two classes too, or modify the display so that it no longer refers to them.

The source describes this strong coupling directly. The display would depend on the specific panel and menus classes, so reuse would drag those classes along.

Mistakes When Reasoning About Events

  • Common mistake

    Assuming the emitter must call the listeners because they respond to it

    What it looks like

    Reading the viewer and concluding that MandelbrotDisplay calls disableMenus on the Menus class

    Why it fails

    The source says the display only announces that a computation has begun. The listener in Menus is the one that acts.

    Do this instead

    Look for the announcement, then for the listener that was set up to hear it.

  • Common mistake

    Thinking that using events always removes all coupling

    What it looks like

    Concluding that MandelbrotPanel should also communicate with MandelbrotDisplay through events

    Why it fails

    The source notes that MandelbrotPanel holds the display directly, and that this matches its design. Not all strong coupling is bad.

    Do this instead

    Ask whether the dependency reflects the design. Use events where reuse and independence matter.

  • Common mistake

    Treating the emitter's knowledge of its listeners as harmless

    What it looks like

    Adding a call inside the display that names a specific new panel class

    Why it fails

    Naming a specific class in the emitter re-creates strong coupling and ties the display to that class.

    Do this instead

    Keep the emitter's code unaware of its listeners and let them subscribe to its events.

  • Common mistake

    Confusing the event type with the listener, since both appear in the same program description

Practice Identifying Emitters and Listeners

EASY

A program has a Scoreboard class that tracks points and announces each change in the score as an event. A ScorePanel class and a SoundEffects class each set up a listener for that event. Identify the emitter, name the listeners, and state whether the Scoreboard names either listener in its own code. Then decide whether the Scoreboard could be reused in a program that has no sound effects.

Hints
  • Look for the class that announces the change, which is the emitter.
  • Listeners are the classes that set up something to hear the announcement.
  • If the emitter does not name the listeners, a program can drop one of them without changing the emitter.

Key Takeaways

  • Event-oriented programming lets one class emit events that other classes listen for and respond to, so the emitter does not call its listeners directly.
  • Strong coupling means one class directly calls methods in another; weak coupling means classes communicate indirectly, such as through events.
  • In the Mandelbrot Viewer, MandelbrotDisplay emits events while MandelbrotPanel and Menus listen and react, which lets the display be reused without modification.
  • Direct references are acceptable when the dependency matches the design, as with MandelbrotPanel holding a MandelbrotDisplay.
  • To analyze a program, identify the emitter, the listeners, and whether the emitter names any listener in its own code.