Events und Zuhörer

Wie erstellen Sie ein benutzerdefiniertes Ereignis und wie lösen Sie es aus, damit eine Komponente ein Ereignis erhalten kann?

Bevor Sie sich ein benutzerdefiniertes Ereignis ansehen, schauen wir uns ein bereits vorhandenes Ereignis an: das ActionEvent.

Komponenten wie Buttonund JButtonfeuern ab ActionEvents, um eine komponentendefinierte Aktion anzuzeigen. Zum Beispiel wird das Buttonausgelöst, ActionEventwenn der Benutzer darauf drückt. Der gesamte Zweck eines Ereignisses besteht darin, einen Listener darüber zu informieren, dass mit einer Komponente in der GUI etwas passiert ist. Ein Ereignis enthält alle Informationen, die ein Hörer benötigt, um herauszufinden, was passiert ist und mit wem es passiert ist (was und wer des Ereignisses). Ein Ereignis muss genügend Informationen enthalten, um sich selbst vollständig zu beschreiben. Auf diese Weise kann ein Zuhörer herausfinden, was genau passiert ist, und auf sinnvolle Weise reagieren.

Das ActionEvententhält Methoden zum Erlernen der Befehlszeichenfolge, der Modifikatoren und der Identifikationszeichenfolge der Aktion. Die getActionCommand()Methode gibt die Befehlszeichenfolge zurück, die die beabsichtigte Aktion des Ereignisses angibt, z. B. Drucken oder Kopieren (das Was). Die getSource()Methode gibt das Objekt zurück, das das Ereignis generiert (das Who).

Um eine zu empfangen ActionEvent, muss ein Listener die ActionListenerSchnittstelle implementieren und sich bei der Komponente registrieren. Darüber hinaus muss eine Komponente ihre Listener im Auge behalten, um sie über ein Ereignis zu informieren.

Anhand des ActionEventBeispiels als Modell können wir leicht die Teile sehen, die für eine Komponente zum Generieren eines Ereignisses und einen Listener zum Abhören eines Ereignisses erforderlich sind. Auf hohem Niveau gibt es drei Teile:

  1. Die Komponente
  2. Die Ereignisklasse
  3. Die Listener-Oberfläche

Schauen wir uns jeden einzeln an.

Die Komponente

Komponenten erzeugen Ereignisse. Ein Ereignis ist die Methode einer Komponente, um einen Hörer wissen zu lassen, dass etwas passiert ist. Daher muss eine Komponente einen Mechanismus zum Registrieren und Abmelden von Ereignis-Listenern bereitstellen. Die Komponente muss auch ihre Listener verfolgen und die Ereignisse an diese Listener weitergeben.

Die Mechanismen der Registrierung / Abmeldung und Nachverfolgung bleiben der einzelnen Komponente überlassen. Eine Komponente verfügt jedoch normalerweise über ein addXXXListenerund removeXXXListenerfür jeden von ihr generierten Ereignistyp. Intern kann die Komponente einen Listener speichern, wie sie möchte. In der Regel speichern Komponenten jedoch Listener in einem java.util.Vectoroder javax.swing.event.EventListenerList. Um ein Ereignis an seine Listener auszulösen, durchläuft die Komponente einfach die Liste der Listener und übergibt das Ereignis an jeden Listener, indem sie die Ereignisversandmethode des Listeners aufruft.

Es ist Zeit für ein Beispiel:

... EventListenerList xxxListeners = new EventListnerList(); public void addXXXListener(XXXListener listener) { xxxListeners.add(XXXListener.class, listener); } public void removeXXXListener(XXXListener listener) { xxxListeners.remove(XXXListener.class, listener); } protected void fireXXX(XXXEvent xxxEvent) { Object[] listeners = xxxListeners.getListenerList(); // loop through each listener and pass on the event if needed Int numListeners = listeners.length; for (int i = 0; i
    

This example shows how to register, deregister, and fire events of type XXXEvent. Listeners can register and deregister themselves through the addXXXListener() and removeXXXListener() methods. When an event occurs, the component creates an event object and passes it to the fireXXX() method, where it is passed to the listeners.

The example defines a generic recipe that all components can follow. However, in order for the example to work, you must define an XXXEvent and an XXXListener interface.

The event class

The event holds all of the information necessary for a listener to figure out what happened. The information included is really event specific. Just think about the event carefully and design the event class to hold whatever information is necessary to fully describe the event to a listener. Events normally extend the java.awt.AWTEvent event class.

The listener interface

An event listener interface defines the methods used by a component to dispatch events. Each event type will have at least one corresponding dispatch method in a listener interface.

A listener interface takes the following generic format:

public interface XXXListener extends EventListener { // event dispatch methods somethingHappened(XXXEvent e); somethingElseHappened(XXXEvent e); ... } 

To listen for an event, a listener must implement the XXXListener interface and register itself with the component. When an event occurs, the component will call the proper dispatch method. The methods are defined in an interface so that any object can receive the event. As long as the listener implements the interface, the component will know how to dispatch the event to the listener.

Wrap-up

As you can see, there are dependencies between some of the pieces. The listener interface corresponds directly to the event. The event is necessarily the dispatch method's argument.

The component corresponds directly with the event and listener. It needs to know about each so that it can create events, dispatch events, and register listeners.

Unlike the other two pieces, the event object is independent. As a result, many components are free to fire off the event type. Furthermore, multiple interfaces may define methods to dispatch the event.

Tony Sintes is a principal consultant at BroadVision. Tony, a Sun-certified Java 1.1 programmer and Java 2 developer, has worked with Java since 1997.

This story, "Events and listeners" was originally published by JavaWorld .