Eventi e ascoltatori

Come si crea un evento personalizzato e come si attiva in modo che un componente possa ottenere un evento?

Prima di guardare un evento personalizzato, diamo un'occhiata a un evento preesistente: il ActionEvent.

Componenti come Buttone si JButtonattivano ActionEventsper indicare un tipo di azione definita dal componente. Ad esempio, Buttonsi spegne ActionEventogni volta che l'utente lo preme. Lo scopo di un evento è informare un ascoltatore che è successo qualcosa a un componente nella GUI. Un evento include tutte le informazioni di cui un ascoltatore ha bisogno per capire cosa è successo ea chi è successo (cosa e chi dell'evento). Un evento deve fornire informazioni sufficienti per descrivere completamente se stesso. In questo modo, un ascoltatore può capire cosa è successo esattamente e rispondere in modo significativo.

Il ActionEventinclude metodi per l'apprendimento stringa dell'azione di comando, modificatori, e la stringa di identificazione. Il getActionCommand()metodo restituisce la stringa di comando che indica l'azione prevista dell'evento, come print o copy (il cosa). Il getSource()metodo restituisce l'oggetto che genera l'evento (il who).

Per ricevere un ActionEvent, un ascoltatore deve implementare l' ActionListenerinterfaccia e registrarsi con il componente. Inoltre, un componente deve tenere traccia dei suoi ascoltatori per notificare loro un evento.

Utilizzando l' ActionEventesempio come modello, possiamo facilmente vedere i pezzi necessari affinché un componente generi un evento e un ascoltatore per ascoltare un evento. Ad alto livello, ci sono tre pezzi:

  1. Il componente
  2. La classe dell'evento
  3. L'interfaccia dell'ascoltatore

Diamo un'occhiata a ciascuno separatamente.

Il componente

I componenti generano eventi. Un evento è il modo in cui un componente fa sapere a un ascoltatore che è successo qualcosa. Pertanto, un componente deve fornire un meccanismo per registrare e annullare la registrazione dei listener di eventi. Il componente deve anche tenere traccia dei suoi ascoltatori e trasmettere gli eventi a quegli ascoltatori.

I meccanismi di registrazione / cancellazione e tracciamento sono lasciati al singolo componente. Tuttavia, un componente normalmente avrà un addXXXListenere removeXXXListenerper ogni tipo di evento che genera. Internamente, il componente può memorizzare un ascoltatore come preferisce; di solito, tuttavia, i componenti memorizzano i listener in un file java.util.Vectoror javax.swing.event.EventListenerList. Per attivare un evento ai suoi listener, il componente semplicemente scorre il suo elenco di listener e passa l'evento a ciascun listener chiamando il metodo di invio degli eventi dell'ascoltatore.

È il momento per un esempio:

... 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 .