Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger

 << zurück
Java ist auch eine Insel von Christian Ullenboom
Programmieren für die Java 2-Plattform in der Version 5
Java ist auch eine Insel

Java ist auch eine Insel
5., akt. und erw. Auflage
1454 S., mit CD, 49,90 Euro
Galileo Computing
ISBN 3-89842-747-1
gp Kapitel 22 Komponenten durch Bohnen
  gp 22.1 Grundlagen der Komponententechnik
    gp 22.1.1 Brauchen wir Komponenten überhaupt?
    gp 22.1.2 Visuelle und nichtvisuelle Komponenten
    gp 22.1.3 Komponenten-Technologien von Microsoft
  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 Ereignissdowntop

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, sodass 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, wie wir es gesehen haben, meistens visuell, kann aber ebenso 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 Unicast  downtop

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 Multicast. 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 wie eine AWT-Komponente verhält, ist möglich, wenn wir die gleichen Spielregeln beachten. Dazu gehört auch, sich Gedanken über Ausnahmen im Listener zu machen. Tritt nämlich bei einem Listener eine Exception auf, kann die Ereignisquelle die Abarbeitung abbrechen oder nicht. Normalerweise sollte sie aber die anderen Interessenten berücksichtigen.


Galileo Computing

22.7.2 Namenskonvention  toptop

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 namens <eventName>Event aus und informiert jeden Listener, der in der Liste eingetragen ist. Die gemäß den Vorgaben des Listeners implementierten Events können beliebige Namen tragen. Erlaubt die add-Methode nur einen Listener, weil sie nur Unicast gestattet, so muss sie zusätzlich java.util.TooManyListenersException werfen können.

Ein Radio soll WerbungEvent-Objekte aussenden. Wir beginnen mit der Klasse WerbungEvent und WerbungListener.

Listing 22.4   RadioTest.java, Teil 1

import java.util.EventListener;
import java.util.EventObject;
import javax.swing.event.EventListenerList;
class WerbungEvent extends EventObject
{
  String nameDerWerbung;
  WerbungEvent( Object sourceString nameDerWerbung)
  {
    super( source );
    this.nameDerWerbung = nameDerWerbung;
  }
}
interface WerbungListener extends EventListener
{
  void werbungKommt( WerbungEvent e );
}

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

Das Radio soll nun Interessenten an- und abmelden können. Es sendet in einem Thread Werbenachrichten:

Listing 22.5   RadioTest.java, Teil 2

class Radio
{
  private EventListenerList listeners = new EventListenerList();
  Radio()
  {
    new Thread() {
      @Override
      public void run() {
        while ( true )
          notifyWerbung( new WerbungEvent( this"Jetzt platzt auch der Haarknoten"));
      }
    }.start();
  }
  public void addWerbungListener( WerbungListener listener ) {
    listeners.add( WerbungListener.classlistener );
  }
  public void removeWerbungListener( WerbungListener listener ) {
    listeners.remove( WerbungListener.classlistener );
  }
  protected synchronized void notifyWerbung( WerbungEvent e )
  {
    for ( WerbungListener l : listeners.getListeners(WerbungListener.class) )
      l.werbungKommt(e);
  }
}

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

Listing 22.6   RadioTest.java, Teil 3

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() );
  }
}

AWTEventMulticaster

Löst die Bean AWT-Ereignisse aus, 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, sodass eine Verkettung entsteht.

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

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( thisActionEvent.ACTION_PERFORMEDnull) );
}

Die angemeldeten Listener bekommen auf diese Weise ein ActionEvent geliefert. Der letzte Parameter im Konstruktor, der hier mit null belegt 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.
 << zurück




Copyright © Galileo Press GmbH 2005
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, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de