Titel   Inhalt   Suchen   Index   DOC  Handbuch der Java-Programmierung, 7. Auflage
 <<    <     >    >>   API  Kapitel 28 - Event-Handling

28.1 Das Event-Handling seit dem JDK 1.1



28.1.1 Grundlagen

Bei der Programmierung unter einer grafischen Oberfläche erfolgt die Kommunikation zwischen Betriebssystem und Anwendungsprogramm zu einem wesentlichen Teil durch das Versenden von Nachrichten. Die Anwendung wird dabei über alle Arten von Ereignissen und Zustandsänderungen vom Betriebssystem informiert. Dazu zählen beispielsweise Mausklicks, Bewegungen des Mauszeigers, Tastatureingaben oder Veränderungen an der Größe oder Lage des Fensters.

Bei der Verarbeitung des Nachrichtenverkehrs sind zwei verschiedene Arten von Objekten beteiligt. Die Ereignisquellen (Event Sources) sind die Auslöser der Nachrichten. Eine Ereignisquelle kann beispielsweise ein Button sein, der auf einen Mausklick reagiert, oder ein Fenster, das mitteilt, dass es über das Systemmenü geschlossen werden soll. Die Reaktion auf diese Nachrichten erfolgt in den speziellen Ereignisempfängern (den EventListeners); das sind Objekte, die das zum Ereignis passende Empfänger-Interface implementieren. Damit ein Ereignisempfänger die Nachrichten einer bestimmten Ereignisquelle erhält, muss er sich bei dieser registrieren.

Dieses Kommunikationsmodell nennt sich Delegation Event Model oder Delegation Based Event Handling und wurde mit der Version 1.1 des JDK eingeführt. Um beispielsweise auf einen Buttonklick zu reagieren, muss man eine EventListener-Klasse schreiben, instanzieren und bei der Ereignisquelle registrieren.

Wir werden feststellen, dass das Modell eine Vielzahl von unterschiedlichen Möglichkeiten impliziert, Ereignishandler zu implementieren. Diese sind je nach Anwendungsfall unterschiedlich gut oder schlecht geeignet, den jeweiligen Nachrichtenverkehr abzubilden. Wir werden uns in diesem Kapitel insbesondere mit folgenden Entwurfsmustern beschäftigen:

Wir werden uns jede dieser Varianten in den nachfolgenden Abschnitten ansehen und ihre jeweiligen Einsatzmöglichkeiten anhand eines Beispiels aufzeigen. Zunächst sollen jedoch die verschiedenen Ereignistypen sowie die Ereignisempfänger und Ereignisquellen näher beleuchtet werden. Wir wollen dabei (etwas unscharf) die Begriffe Ereignis, Nachricht und Event in diesem Kapitel synonym verwenden, wenn wir innerhalb eines GUI-Programms die ausgetauschten Nachrichten oder ihre auslösenden Ereignisse meinen.

Die Details einzelner Ereignisarten werden in den nachfolgenden Kapiteln schrittweise erklärt und zusammen mit den zugehörigen Ereignisquellen vorgestellt.

28.1.2 Ereignistypen

Die Ereignistypen werden durch eine Hierarchie von Ereignisklassen, die aus der Klasse java.util.EventObject abgeleitet sind, repräsentiert. Die Motivation der Java-Designer, diese Klasse in das Paket java.util zu legen, resultierte wohl aus der Überlegung, dass der Transfer von Nachrichten nicht allein auf den Oberflächenteil beschränkt sein muss, sondern auch zwischen anderen Elementen einer komplexen Anwendung sinnvoll sein kann. Die Klasse java.util.EventObject fungiert damit als allgemeine Oberklasse aller Arten von Ereignissen, die zwischen verschiedenen Programmteilen ausgetauscht werden können. Ihre einzige nennenswerte Fähigkeit besteht darin, das Objekt zu speichern, das die Nachricht ausgelöst hat, und durch Aufruf der Methode getSource anzugeben:

public Object getSource()
java.util.EventObject

Die Hierarchie der AWT-spezifischen Ereignisklassen beginnt eine Ebene tiefer mit der Klasse AWTEvent, die aus EventObject abgeleitet wurde und sich im Paket java.awt befindet. AWTEvent ist Oberklasse aller Ereignisklassen des AWT. Diese befinden sich im Paket java.awt.event, das damit praktisch in jede Klasse einzubinden ist, die sich mit dem Event-Handling von GUI-Anwendungen beschäftigt. Abbildung 28.1 gibt einen Überblick über die Vererbungshierarchie der Ereignisklassen.

Abbildung 28.1: Die Hierarchie der Ereignisklassen

Die Dokumentation zum JDK unterteilt diese Klassen in zwei große Hierarchien. Unterhalb der Klasse ComponentEvent befinden sich alle Low-Level-Ereignisse. Sie sind für den Transfer von elementaren Nachrichten zuständig, die von Fenstern oder Dialogelementen stammen. Die übrigen Klassen ActionEvent, AdjustmentEvent, ItemEvent und TextEvent werden als semantische Ereignisse bezeichnet. Sie sind nicht an ein bestimmtes GUI-Element gebunden, sondern übermitteln höherwertige Ereignisse wie das Ausführen eines Kommandos oder die Änderung eines Zustands.

Ein Problem der AWT-Designer war es, einen guten Kompromiss zwischen der Größe und der Anzahl der zu implementierenden Ereignisklassen zu finden. Da der Ableitungsbaum sehr unübersichtlich geworden wäre, wenn für jedes Elementarereignis eine eigene Klasse implementiert worden wäre, hat man sich teilweise dazu entschlossen, mehrere unterschiedliche Ereignisse durch eine einzige Klasse zu realisieren. So ist beispielsweise die Klasse MouseEvent sowohl für Mausbewegungen als auch für alle Arten von Klick- oder Drag-Ereignissen zuständig. Mit Hilfe der Methode getID und der in den jeweiligen Eventklassen definierten symbolischen Konstanten kann das Programm herausfinden, um welche Art von Ereignis es sich handelt:

 Hinweis 

public int getID()
java.awt.AWTEvent

Falls das Programm eigene Eventklassen definieren will und Konstanten zur Vergabe der Event-Ids vergeben muss, sollten diese oberhalb der symbolischen Konstante RESERVED_ID_MAX liegen.

Die Eventklassen enthalten keine frei zugänglichen Felder. Stattdessen sind alle Eigenschaften durch set-/get-Methoden gekapselt, die je nach Ereignisklasse unterschiedlich sind. So gibt es beispielsweise in MouseEvent die Methode getPoint, mit der die Mauszeigerposition abgefragt werden kann, in KeyEvent die Methode getKeyChar zur Bestimmung der gedrückten Taste und in der übergeordneten Klasse InputEvent die Methode getModifiers, mit der sowohl für Maus- als auch für Tastaturevents der Zustand der Sondertasten bestimmt werden kann. Wir werden bei der Besprechung der einzelnen Ereignisarten auf die Details eingehen.

 Hinweis 

28.1.3 Ereignisempfänger

Damit ein Objekt Nachrichten empfangen kann, muss es eine Reihe von Methoden implementieren, die von der Nachrichtenquelle, bei der es sich registriert hat, aufgerufen werden können. Um sicherzustellen, dass diese Methoden vorhanden sind, müssen die Ereignisempfänger bestimmte Interfaces implementieren, die aus der Klasse EventListener des Pakets java.util abgeleitet sind. Diese EventListener-Interfaces befinden sich im Paket java.awt.event.

Je Ereignisklasse gibt es ein EventListener-Interface. Es definiert eine separate Methode für jede Ereignisart dieser Ereignisklasse. So besitzt beispielsweise das Interface MouseListener die Methoden mouseClicked, mouseEntered, mouseExited, mousePressed und mouseReleased, die bei Auftreten des jeweiligen Ereignisses aufgerufen werden. Abbildung 28.2 gibt eine Übersicht über die Hierarchie der EventListener-Interfaces.

Abbildung 28.2: Die Hierarchie der EventListener-Interfaces

Jede der Methoden eines Listener-Interface enthält als einziges Argument ein Objekt vom zugehörigen Ereignistyp. Alle Methoden sind vom Typ void, erzeugen also keinen Rückgabewert.

 Hinweis 

28.1.4 Ereignisquellen

Die Ereignisse stammen von den Ereignisquellen, also von Fenstern, Dialogelementen oder höheren Programmobjekten. Eine Ereignisquelle sendet aber nur dann Ereignisse an einen Ereignisempfänger, wenn dieser sich bei der Ereignisquelle registriert hat. Fehlt eine solche Registrierung, wird die Ereignisquelle keine Ereignisse senden und der Empfänger folglich auch keine erhalten.

Die Registrierung erfolgt mit speziellen Methoden, an die ein Objekt übergeben wird, das das jeweilige EventListener-Interface implementiert. So gibt es beispielsweise eine Methode addMouseListener in der Klasse Component, mit der ein Objekt, das das Interface MouseListener implementiert, sich für den Empfang von Mausereignissen bei der Komponente registrieren lassen kann. Nach erfolgter Registrierung wird bei jedem Mausereignis die entsprechende Methode mouseClicked, mouseEntered, mouseExited, mousePressed oder mouseReleased aufgerufen.

Die Ereignisquellen unterstützen das Multicasting von Ereignissen. Dabei kann eine Ereignisquelle nicht nur einen einzelnen EventListener mit Nachrichten versorgen, sondern eine beliebige Anzahl von ihnen. Jeder Aufruf von addXYZListener registriert dabei einen weiteren Listener in der Ereignisquelle. Das AWT definiert nicht, in welcher Reihenfolge die verschiedenen Ereignisempfänger beim Auftreten eines Ereignisses aufgerufen werden, und empfiehlt den Programmen, hierüber keine Annahmen zu treffen.

 Hinweis 

28.1.5 Adapterklassen

Eine Adapterklasse in Java ist eine Klasse, die ein vorgegebenes Interface mit leeren Methodenrümpfen implementiert. Adapterklassen können verwendet werden, wenn aus einem Interface lediglich ein Teil der Methoden benötigt wird, der Rest aber uninteressant ist. In diesem Fall leitet man einfach eine neue Klasse aus der Adapterklasse ab, anstatt das zugehörige Interface zu implementieren, und überlagert die benötigten Methoden. Alle übrigen Methoden des Interface werden von der Basisklasse zur Verfügung gestellt.

Zu jedem der Low-Level-Ereignisempfänger stellt das Paket java.awt.event eine passende Adapterklasse zur Verfügung. So gibt es die Adapterklassen FocusAdapter, KeyAdapter, MouseAdapter, MouseMotionAdapter, ComponentAdapter, ContainerAdapter und WindowAdapter. Sie implementieren die korrespondierenden Interfaces. Wir werden später bei der Beschreibung der lokalen und anonymen Klassen sehen, wie die Adapterklassen bei der Realisierung der Ereignisempfänger hilfreich sein können.

28.1.6 Zusammenfassung

Der folgende Überblick bündelt die bisherigen Ausführungen und gibt eine Zusammenfassung aller Ereignisse nebst zugehörigen Ereignisempfängern und ihren Methoden. Außerdem sind die Ereignisquellen und die Methoden zur Registrierung der Ereignisse angegeben. Jeder Ereignistyp wird dabei durch zwei Tabellen dargestellt. Die erste gibt die zugehörige Ereignisklasse, das Listener-Interface und den Namen der Methode zur Registrierung von Ereignisempfängern an. Sie listet außerdem die als Ereignisquelle in Frage kommenden Klassen auf. Die zweite Tabelle enthält alle Methoden des zugehörigen Listener-Interface und beschreibt damit die zu diesem Ereignistyp gehörenden Elementarereignisse.

Dieser Abschnitt nimmt damit Informationen vorweg, die in späteren Teilen des Buchs konkretisiert werden. Obwohl zum jetzigen Zeitpunkt nicht alle Ereignisse in ihrer vollen Bedeutung dargestellt werden können, mag diese Übersicht für die weitere Arbeit mit dem AWT und zum Nachschlagen hilfreich sein.

Focus-Ereignisse

Eigenschaft Klasse, Interface oder Methode
Ereignisklasse FocusEvent
Listener-Interface FocusListener
Registrierungsmethode addFocusListener
Mögliche Ereignisquellen Component

Tabelle 28.1: Focus-Ereignisse

Ereignismethode Bedeutung
focusGained Eine Komponente erhält den Focus.
focusLost Eine Komponente verliert den Focus.

Tabelle 28.2: Methoden für Focus-Ereignisse

Key-Ereignisse

Eigenschaft Klasse, Interface oder Methode
Ereignisklasse KeyEvent
Listener-Interface KeyListener
Registrierungsmethode addKeyListener
Mögliche Ereignisquellen Component

Tabelle 28.3: Key-Ereignisse

Ereignismethode Bedeutung
keyPressed Eine Taste wurde gedrückt.
keyReleased Eine Taste wurde losgelassen.
keyTyped Eine Taste wurde gedrückt und wieder losgelassen.

Tabelle 28.4: Methoden für Key-Ereignisse

Mouse-Ereignisse

Eigenschaft Klasse, Interface oder Methode
Ereignisklasse MouseEvent
Listener-Interface MouseListener
Registrierungsmethode addMouseListener
Mögliche Ereignisquellen Component

Tabelle 28.5: Mouse-Ereignisse

Ereignismethode Bedeutung
mouseClicked Eine Maustaste wurde gedrückt und wieder losgelassen.
mouseEntered Der Mauszeiger betritt die Komponente.
mouseExited Der Mauszeiger verlässt die Komponente.
mousePressed Eine Maustaste wurde gedrückt.
mouseReleased Eine Maustaste wurde losgelassen.

Tabelle 28.6: Methoden für Mouse-Ereignisse

MouseMotion-Ereignisse

Eigenschaft Klasse, Interface oder Methode
Ereignisklasse MouseEvent
Listener-Interface MouseMotionListener
Registrierungsmethode addMouseMotionListener
Mögliche Ereignisquellen Component

Tabelle 28.7: MouseMotion-Ereignisse

Ereignismethode Bedeutung
mouseDragged Die Maus wurde bei gedrückter Taste bewegt.
mouseMoved Die Maus wurde bewegt, ohne dass eine Taste gedrückt wurde.

Tabelle 28.8: Methoden für MouseMotion-Ereignisse

Component-Ereignisse

Eigenschaft Klasse, Interface oder Methode
Ereignisklasse ComponentEvent
Listener-Interface ComponentListener
Registrierungsmethode addComponentListener
Mögliche Ereignisquellen Component

Tabelle 28.9: Komponenten-Ereignisse

Ereignismethode Bedeutung
componentHidden Eine Komponente wurde unsichtbar.
componentMoved Eine Komponente wurde verschoben.
componentResized Die Größe einer Komponente hat sich geändert.
componentShown Eine Komponente wurde sichtbar.

Tabelle 28.10: Methoden für Komponenten-Ereignisse

Container-Ereignisse

Eigenschaft Klasse, Interface oder Methode
Ereignisklasse ContainerEvent
Listener-Interface ContainerListener
Registrierungsmethode addContainerListener
Mögliche Ereignisquellen Container

Tabelle 28.11: Container-Ereignisse

Ereignismethode Bedeutung
componentAdded Eine Komponente wurde hinzugefügt.
componentRemoved Eine Komponente wurde entfernt.

Tabelle 28.12: Methoden für Container-Ereignisse

Window-Ereignisse

Eigenschaft Klasse, Interface oder Methode
Ereignisklasse WindowEvent
Listener-Interface WindowListener
Registrierungsmethode addWindowListener
Mögliche Ereignisquellen Dialog, Frame

Tabelle 28.13: Window-Ereignisse

Ereignismethode Bedeutung
windowActivated Das Fenster wurde aktiviert.
windowClosed Das Fenster wurde geschlossen.
windowClosing Das Fenster wird geschlossen.
windowDeactivated Das Fenster wurde deaktiviert.
windowDeiconified Das Fenster wurde wiederhergestellt.
windowIconified Das Fenster wurde auf Symbolgröße verkleinert.
windowOpened Das Fenster wurde geöffnet.

Tabelle 28.14: Methoden für Window-Ereignisse

Action-Ereignisse

Eigenschaft Klasse, Interface oder Methode
Ereignisklasse ActionEvent
Listener-Interface ActionListener
Registrierungsmethode addActionListener
Mögliche Ereignisquellen Button, List, MenuItem, TextField

Tabelle 28.15: Action-Ereignisse

Ereignismethode Bedeutung
actionPerformed Eine Aktion wurde ausgelöst.

Tabelle 28.16: Methoden für Action-Ereignisse

Adjustment-Ereignisse

Eigenschaft Klasse, Interface oder Methode
Ereignisklasse AdjustmentEvent
Listener-Interface AdjustmentListener
Registrierungsmethode addAdjustmentListener
Mögliche Ereignisquellen Scrollbar

Tabelle 28.17: Adjustment-Ereignisse

Ereignismethode Bedeutung
adjustmentValueChanged Der Wert wurde verändert.

Tabelle 28.18: Methoden für Adjustment-Ereignisse

Item-Ereignisse

Eigenschaft Klasse, Interface oder Methode
Ereignisklasse ItemEvent
Listener-Interface ItemListener
Registrierungsmethode addItemListener
Mögliche Ereignisquellen Checkbox, Choice, List, CheckboxMenuItem

Tabelle 28.19: Item-Ereignisse

Ereignismethode Bedeutung
itemStateChanged Der Zustand hat sich verändert.

Tabelle 28.20: Methoden für Item-Ereignisse

Text-Ereignisse

Eigenschaft Klasse, Interface oder Methode
Ereignisklasse TextEvent
Listener-Interface TextListener
Registrierungsmethode addTextListener
Mögliche Ereignisquellen TextField, TextArea

Tabelle 28.21: Text-Ereignisse

Ereignismethode Bedeutung
textValueChanged Der Text wurde verändert.

Tabelle 28.22: Methoden für Text-Ereignisse


 Titel   Inhalt   Suchen   Index   DOC  Handbuch der Java-Programmierung, 7. Auflage, Addison Wesley, Version 7.0
 <<    <     >    >>   API  © 1998, 2011 Guido Krüger & Heiko Hansen, http://www.javabuch.de