Weitere aktuelle Java-Titel finden Sie bei dpunkt.
 Inhaltsverzeichnis   Auf Ebene Zurück   Seite Zurück   Seite Vor   Auf Ebene Vor   Eine Ebene höher   Index


9.4

Erzeugen eigener Ereignisse


In vielen Situationen reicht es nicht aus, die Komponenten in der vordefinierten Form zu benutzen. Sie müssen an die individuellen Anforderungen des Benutzers angepasst werden. Dies kann z. B. der Fall sein, wenn eine Komponente auf ein bestimmtes Ereignis reagieren soll. In den meisten Fällen ist es notwendig, eine eigene Klasse von einer Komponente abzuleiten, um bei komplexen Oberflächen die Ereignisabarbeitung zu trennen. Durch die Definition eigener Klassen wird das Programm überschaubarer und strukturierter. Das AWT verfügt über viele vordefinierte Ereignisse, die in den Standardklassen ausgelöst werden können. Für eine gute Trennung der Ereignisverarbeitung von der Implementierung der Klasse, sollte man auch in benutzerdefinierten Komponenten Ereignisse definieren, soweit dies Sinn macht.

Bei der Implementierung eines benutzerdefinierten Ereignisses wird prinzipiell folgendermaßen vorgegangen: In diesem Abschnitt wird die Implementierung einer Klasse demonstriert, die zur Passworteingabe verwendet wird. Die visuelle Repräsentation erfolgt in Form eines Textfelds. Bei jeder Eingabe in das Textfeld wird ein Stern ausgegeben, damit das eingegebene Passwort nicht gesehen werden kann. Komponenten, die über den Erfolg oder Misserfolg einer Passworteingabe informiert werden wollen, müssen sich bei dem Textfeld registrieren. Wird eine Passworteingabe durch Drücken der return-Taste abgeschlossen, werden alle registrieren Event-Listener über das Ereignis informiert. Im folgenden werden die oben genannten Schritt an diesem Beispiel demonstriert.

Die Definition des Event-Objekts ist recht einfach:
  public class AuthentificationEvent extends EventObject {
    public final static int AUTHENTIFICATION_SUCCEEDED = 10001;
    public final static int AUTHENTIFICATION_FAILED = 10002;
    protected int id;
    protected String password;
  
    public AuthentificationEvent(Object source, int id, String password) {
      super(source);
      this.id = id;
      this.password = password;
    }
  
    int getID() {
      return id;
    }
  
    String getPassword() {
      return password;
    }
  }
Die Klasse AuthentificationEvent enthält Informationen über eine Passworteingabe. Der Konstruktor erhält das Passwort übergeben, das vom Benutzer eingegeben wurde und einen Verweis auf das Objekt, in dem das Ereignis stattgefunden hat. Außerdem wird eine ID gespeichert, die anzeigt, ob das eingegebene Passwort korrekt oder falsch war. Als Werte für diese ID werden zwei Konstanten definiert.

Im EventListener-Interface werden zwei Methoden definiert:
public interface AuthentificationListener extends EventListener {

  public void authentificationSucceeded(AuthentificationEvent e);
  public void authentificationFailed(AuthentificationEvent e);

}
Dieses Interface muss; von Objekten implementiert werden, die über den Status einer Passworteingabe informiert werden wollen. authentificationSucceeded() wird bei Eingabe des richtigen Passworts, authentificationFailed() bei Eingabe des falschen Passworts aufgerufen.

PasswordTextField ist die Klasse, die die eigentliche Komponente darstellt.
  public PasswordTextField(String password) {
    // Speichern des Passwortes
    this.password = password;
    // Stern als Ausgabezeichen setzen
    setEchoChar('*');
    enableEvents(AWTEvent.ACTION_EVENT_MASK);
    multicaster = new AuthentificationEventMulticaster();
  }

Der Konstruktor der Klasse bekommt das richtige Passwort übergeben und merkt es sich in einem Datenelement. Außerdem wird dort ein Exemplar der Klasse AuthentificationEventMulticaster erzeugt und ebenfalls in einem Datenelement gespeichert. Diese Klasse ist später für das Verteilen der Ereignisse an die unterschiedlichen Listener zuständig. Mit folgenden Methoden können sich die Listener bei dem Textfeld für die Passworteingabe registrieren bzw. wieder abmelden:
  public void addAuthentificationListener(
                         AuthentificationListener l) {
    multicaster.add(l);
  }

  public void removeActionListener(
                         AuthentificationListener l) {
    multicaster.remove(l);
  }

Wie zu sehen ist, werden die neuen Listener an den AuthentificationEventMulticaster weitergeleitet. Dort erfolgt also die Verwaltung der Listener.

Da die hier vorgestellte Klasse eine eigenständige Komponente darstellt, wird die interne Ereignisverarbeitung durch die processXXXEvent()-Methoden vorgenommen.

Nach Abschluss einer Eingabe in das Textfeld durch Drücken der Return-Taste muss geprüft werden, ob der eingegebene Text mit dem Passwort übereinstimmt, das dem Konstruktor übergeben wurde. Hierfür ist lediglich die Implementierung der Methode processActionEvent() notwendig:
  public void processActionEvent(ActionEvent e) {
    // Ist das Passwort gleich dem Eingabetext?
    if (password.equals(e.getActionCommand()))
      // Wenn ja, Passwort korrekt
      multicaster.authentificationSucceeded(
      new AuthentificationEvent(this,
             AuthentificationEvent.AUTHENTIFICATION_SUCCEEDED,
             e.getActionCommand()));
    else
      // Sonst Passwort nicht korrekt
      multicaster.authentificationFailed(
      new AuthentificationEvent(this,
             AuthentificationEvent.AUTHENTIFICATION_FAILED,
             e.getActionCommand()));
    if(clearAfterInput)
      setText("");
  }

Stimmt die Eingabe mit dem Passwort überein, müssen alle Event-Listener entsprechend darüber informiert werden. Hierzu wird die Methode authentificationSucceeded() des AuthentificationEventMulticaster aufgerufen. Als Argument wird ein neues Exemplar der Klasse AuthentificationEvent übergeben, initialisiert mit den entsprechenden Parametern. Analoges gilt für die falsche Eingabe eines Passworts.

AuthentificationEventMulticaster ist eine Klasse, die selbst das Interface AuthentificationListener implementiert. Deshalb werden dort ebenfalls, wie in allen anderen Event-Listenern auch, die Methoden authentificationSucceeded() und authentificationFailed() implementiert. In dieser Implementierung wird jedoch lediglich das neu erzeugte Exemplar von AuthentificationEvent an alle registrierten Listener verteilt:
  public class AuthentificationEventMulticaster
                   implements AuthentificationListener {
    protected Vector listener = new Vector();
  
    public void remove(AuthentificationListener l) {
      listener.remove(l);
    }
  
    public void authentificationSucceeded(
                                AuthentificationEvent e) {
      for(int i=0; i < listener.size(); i++)
        ((AuthentificationListener)listener.elementAt(i)).
                             authentificationSucceeded(e);
    }
  
    public void authentificationFailed(
                                AuthentificationEvent e) {
      for(int i=0; i < listener.size(); i++)
        ((AuthentificationListener)listener.elementAt(i)).
                                authentificationFailed(e);
    }
  
    public void add(AuthentificationListener a) {
      if(! listener.contains(a))
        listener.addElement(a);
    }
  }
Hierdurch erfolgt das Verteilen des Event-Objektes transparent für die eigentliche Komponente, da die Verwaltung der Listener komplett in eine eigene Klasse ausgelagert wurde. Die Klasse AuthentificationEventMulticaster aus diesem Beispiel ist nicht besonders ökonomisch, dafür aber relativ leicht verständlich implementiert. Im Paket java.awt ist die Klasse AWTEventMulticaster definiert, die einen viel effizienteren Mechanismus für das Verteilen von Ereignissen bereitstellt. Durch diese Klassen werden alle Ereignisse im AWT an die Event-Listener geschickt.

Material zum Beispiel


 Inhaltsverzeichnis   Auf Ebene Zurück   Seite Zurück   Seite Vor   Auf Ebene Vor   Eine Ebene höher   Index

Copyright © 2002 dpunkt.Verlag, Heidelberg. Alle Rechte vorbehalten.