Galileo Computing < openbook >
Galileo Computing - Professionelle Buecher. Auch fuer Einsteiger.
Galileo Computing - Professionelle Buecher. Auch fuer Einsteiger.


Java ist auch eine Insel von Christian Ullenboom
Buch: Java ist auch eine Insel (Galileo Computing)
gp Kapitel 22 Komponenten durch Bohnen
gp 22.1 Grundlagen der Komponententechnik
gp 22.1.1 Brauchen wir überhaupt Komponenten?
gp 22.1.2 Visuelle und nichtvisuelle Komponenten
gp 22.1.3 Andere Komponententechnologien oder: Was uns Microsoft brachte
gp 22.2 Das JavaBeans Development Kit (BDK)
gp 22.2.1 Eine Beispielsitzung im BDK
gp 22.2.2 Verknüpfungen zwischen Komponenten
gp 22.2.3 Beans speichern
gp 22.3 Die kleinste Bohne der Welt
gp 22.4 Jar-Archive für Komponenten
gp 22.5 Worauf JavaBeans basieren
gp 22.6 Eigenschaften
gp 22.6.1 Einfache Eigenschaften
gp 22.6.2 Boolesche Eigenschaften
gp 22.6.3 Indizierte Eigenschaften
gp 22.7 Ereignisse
gp 22.7.1 Multicast und Unicast
gp 22.7.2 Namenskonvention
gp 22.8 Weitere Eigenschaften
gp 22.8.1 Gebundene Eigenschaften
gp 22.8.2 Anwendung von PropertyChange bei AWT-Komponenten
gp 22.8.3 Veto-Eigenschaften. Dagegen!
gp 22.9 Bean-Eigenschaften anpassen
gp 22.9.1 Customizer
gp 22.10 Property-Editoren
gp 22.11 BeanInfo
gp 22.12 Beliebte Fehler


Galileo Computing

22.7 Ereignissedowntop

Ereignisse informieren Objekte über Zustandsänderungen anderer Objekte. Auch unsere Beans können Statusmeldungen absetzen. Komponenten können in einem Application-Builder untereinander verbunden werden, so dass eine Komponente als Quelle für Ereignisse dient und Zuhörer dieses Ereignis abfangen und auswerten können. Die Zuhörer heißen im Folgenden auch Interessenten.

Die Verknüpfung der Ereignisse ist, so wie wir es gesehen haben, meistens visuell, kann aber genauso gut von Hand programmiert werden. Für die Benutzung unterscheiden sich die Bean-Ereignisse nicht von AWT-Ereignissen, die wir schon oft verwendet haben; nur treten wir hier als Anbieter (Implementierer) auf und nicht als Nutzer. Obwohl in der Regel die Interessenten eine Schnittstelle implementieren, können wir auch Adaptoren anbieten.


Galileo Computing

22.7.1 Multicast und Unicastdowntop

Normalerweise können mit einer Komponente beliebig viele Zuhörer verbunden werden. Tritt ein Ereignis auf, dann informiert die Komponente alle Interessierten. Dies nennt sich Mulitcast. Eine Einschränkung davon ist Unicast: dann darf sich nur ein Interessent anmelden. Versucht es ein zweiter, wird eine Ausnahme ausgelöst.

Dass sich also unsere Bean so verhält wie eine AWT-Komponente, ist möglich, wenn wir die gleichen Spielregeln beachten. Dazu gehört, sich Gedanken über Ausnahmen im Listener zu machen. Denn tritt bei einem Listener eine Exception auf, dann kann die Ereignisquelle die Abarbeitung abbrechen oder nicht. Normalerweise sollte sie aber die anderen Interessenten berücksichtigen.


Galileo Computing

22.7.2 Namenskonventiontoptop

Genau wie für Eigenschaften gibt es für Ereignisse und die damit verbundenen Schnittstellen eigene Namenskonventionen. Interessierte Objekte sollen die Bean-Methoden add<Bean>Listener() und remove<Bean>Listener() aufrufen können. Die Bean löst ihrerseits ein Ereignis mit dem Namen <eventName>Event aus und informiert jeden Listener, der in der Liste eingetragen ist. Die Events, die gemäß den Vorgaben des Listeners implementiert werden müssen, können beliebige Namen tragen. Erlaubt die add-Methode nur einen Listener, weil sie nur Unicast erlaubt, muss sie zusätzlich java.util.TooManyListeners Exception werfen können.


Beispiel Ein Radio wirft in regelmäßigen Abständen WerbungEvent-Objekte aus. Die Signaturen und Klassen sehen skizziert wie folgt aus:

Listing 22.4 RadioTest.java, Teil 1

import java.util.*;
class WerbungEvent extends EventObject
{
  String nameDerWerbung;
  WerbungEvent( Object source, String nameDerWerbung)
  {
    super( source );
    this.nameDerWerbung = nameDerWerbung;
  }
}
interface WerbungListener extends EventListener
{
  void werbungKommt( WerbungEvent e );
}
class Radio
{
  private Vector listeners = new Vector();
  Radio()
  {
    new Thread() {
      public void run() {
        while ( true )
          notifyWerbung( new WerbungEvent( this,
            "Jetzt platzt auch der Haarknoten"));
      }
    }.start();
  }
  public void addWerbungListener( WerbungListener listener ) {
    listeners.addElement( listener );
  }
  public void removeWerbungListener( WerbungListener listener ) {
    listeners.removeElement( listener );
  }
  protected synchronized void notifyWerbung( WerbungEvent e )
  {
    for ( int i = 0; i < listeners.size(); i++ )
     ((WerbungListener)listeners.elementAt(i)).werbungKommt(e);
  }
}

Die Schnittstelle EventListener ist im Übrigen nur eine Markierungsschnittstelle, doch alle Ereignis-Listener müssen sie erweitern.

Die Anwendung nutzt jetzt das Radio-Objekt und implementiert einen konkreten WerbungListener, etwa so:

Listing 22.5 RadioTest.java, Teil 2

class MyWerbungListener implements WerbungListener
{
  public void werbungKommt( WerbungEvent e )
  {
     System.out.println( "Oh nein, schon wieder Werbung: " + e.nameDerWerbung );
  }
}
public class RadioTest
{
  public static void main( String args[] )
  {
    Radio r = new Radio();
    r.addWerbungListener( new MyWerbungListener() );
  }
}

Beispiel Löst die Bean AWT-Ereignisse aus, so kann sie dafür AWTEventMulticaster nutzen. Diese Klasse ist für effizientes Multicast-Benachrichtigen bei AWT-Ereignissen gedacht. Genau genommen verbindet sie dazu nur zwei EventListener miteinander, so dass eine Verkettung entsteht.

protected ActionListener listeners;
public void addActionListener( ActionListener l ) {
  listeners = AWTEventMulticaster.add( l, listeners );
}
public void removeActionListener( ActionListener l ) {
  listeners = AWTEventMulticaster.remove( l, listeners );
}

Da AWTEventMulticaster alle möglichen AWT-Listener implementiert, können wir die Methode actionPerformed(), die die Schnittstelle ActionListener vorschreibt, aufrufen. Wenn wir ACTION_PERFORMED-Nachrichten damit generieren, schreiben wir Folgendes in unsere Bean-Klasse.

protected void fireActionEvent () {
  if ( listeners != null )
    listeners.actionPerformed(
      new ActionEvent( this, ActionEvent.ACTION_PERFORMED, null) );
}

Die angemeldeten Listener bekommen so ein ActionEvent geliefert. Der letzte Parameter im Konstruktor, der null gewählt ist, kann zusätzlich eine Referenz übermitteln.


class java.awt.event.AWTEventMulticaster
implements ComponentListener, ContainerListener, FocusListener, KeyListener,
 MouseListener, MouseMotionListener, WindowListener, ActionListener,
ItemListener, AdjustmentListener, TextListener, InputMethodListener,
 HierarchyListener, HierarchyBoundsListener

gp static ActionListener add( ActionListener a, ActionListener b )
Verbindet Listener a und b und liefert ein neues ActionListener-Objekt zurück.
gp static ActionListener remove( ActionListener l, ActionListener oldl )
Entfernt Listener oldl von l und liefert den neuen Multicast-Listener zurück.

class java.awt.event.ActionEvent
extends AWTEvent

gp ActionEvent( Object source, int id, String command )
Erzeugt ein ActionEvent mit Quelle, die das Ereignis ausgelöst hat, einen Identifizierer und ein Kommando.




Copyright (c) Galileo Press GmbH 2004
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de