In der Ereignisverarbeitung erfolgt ein Großteil der Aktionen Ihrer Anwendung. Bisher hat sich dieses Buch auf die grafische Schnittstelle zwischen Ihrer Anwendung und dem Anwender konzentriert. Jetzt wollen wir sehen, wie diese wunderbare Oberfläche zum Leben erweckt werden kann.
Java-Anwendungen reagieren durch Ereignsisse auf Nachrichten, die ihnen das System sendet. Wenn ein Anwender auf eine Schaltfläche klickt, ein Menüelement auswählt oder Text eingibt, wird dadurch eine Nachricht an Ihre Anwendung geschickt.
Das heutige Projekt heißt HandlingEvents.jpr, dem alle Listings hinzugefügt werden.
Wie Sie in den vergangenen Lektionen gesehen haben, ist es ganz einfach, Ereignis-Handler zu entwickeln. Sie wählne im Visual-Designer-Modus die Komponente im Designer oder im Menü-Designer, für den ein Ereignis verarbeitet werden soll - ein Menübefehl, eine Schaltfläche o.ä.
Um einen neuen Ereignis-Handler zu entwickeln, klicken Sie im Inspektor-Fenster auf die Registerkarte Ereignis und wählen dann das Ereignis aus, für das Sie eine Methode schreiben wollen. Klicken Sie einmal auf die rechte Spalten, um eine neue Methode anzugeben, und doppelklicken Sie dann, um den Fokus auf die Registerkarte Quelltext im AppBrowser zu verschieben. Der Cursor wird in dem Quellcode Ihrer neuen Methode zur Ereignisverarbeitung positioniert, und Sie können Ihre Befehle eingeben. Diese Prozedur haben Sie in Lektion 6 bereits kennengelernt. .
Wenn Sie einen existierenden Ereignis verwenden wollen, klicken Sie auf die Ereignis-Registerkarte und wählen ein Ereignis aus, für das Sie den existierenden Ereignis-Handler verwenden wollen. Klicken Sie auf die rechte Spalten und geben Sie den Namen der existierenden Methode ein. Das ist alles! Ihre Komponente oder Ihr Menüeintrag verwenden jetzt diese Methode für ihre eigenen Ereignisse.
Eine schnelle Methode, den Standard-Ereignis-Handler für eine Komponente zu erzeugen, ist, im Visual Designer auf die Komponente doppelzuklicken. Für die meisten Komponenten ist ein Standard-Ereignis definiert. Das Standard-Ereignis für eine Schaltfläche beispielsweise ist actionPerformed, und der Standard-Ereignis-Handler ist actionPerformed_buttonName. Das Ereignis actionPerformed ist auch der Standard für Komponenten, die keinen expliziten Standard definieren.
Wenn Sie einen Ereignis-Handler erzeugen, erzeugt die IDE neben dem Methoden-Rumpf automatisch den Code, der die Methode mit der Komponente verbindet. Unter anderem handelt es sich dabei um einen EventAdapter und einen EventListener, die als neue Klassen in Ihrem Quellcode erzeugt werden - diesen Code sollten Sie nicht verändern. Wie diese Klassen funktionieren, kann in diesem Buch nicht erklärt werden, aber sie stellen ein weiteres Beispiel dar, wie die IDE es vereinfacht, Java-Code zu schreiben. Immer wenn Sie Ihrem Projekt einen Frame hinzufügen, fügt die IDE außerdem automatisch die entsprechende Import-Zeile ein:
Damit können Ereignisse korrekt verarbeitet werden, wenn Sie Code für die Ereignisverarbeitung einfügen.
Um einen Ereignis-Handler zu löschen, wählen Sie seinen Namen in der rechten Spalte des Ereignisses und drücken die Entfernen-Taste. Dadurch wird der Ereignis-Handler von dem Ereignis gelöst, aber dadurch wird die Methode zur Ereignisverarbeitung noch nicht gelöscht. Das ist eine Sicherheitsfunktion, so daß eine Methode nicht einfach gelöscht werden kann, nur weil Sie gerade den letzten Verweis darauf gelöscht haben. (Vielleicht brauchen Sie sie später ja noch einmal.)
Um die Methode zur Ereignisverarbeitung ganz aus Ihrem Quellcode zu entfernen, entfenren Sie den Methoderumpf und lassen die leere Methodensignatur zurück. Beim nächsten Kompilieren wird der Code für diesen Handler (auch der automatisch erzeugte) aus Ihrer Quellcode-Datei entfernt.
Java-Ereignisse sind Teil des AWT-Pakets. Ein Ereignis stellt eine Möglichkeit dar, wie Komponenten mit Ihnen als Programmierer und mit anderen Komponenten kommunizieren. Dabei kann es um Eingaben vom Anwender (Mausklicks, Mausbewegungen, Tastencodes) Änderungen der Systemumgebung (ein Fenster hat sich geöffnet oder wurde geschlossen, das Fenster wurde gescrollt) oder zahllose andere Dinge handeln, die die Arbeitsweise des Programms auf irgendeine Weise beeinflußen.
Mit anderen Worten, wenn etwas in einer Komponente passiert, wird ein Ereignis erzeugt. Einige Ereignisse werden implizit verarbeitet, ohne daß Sie irgend etwas dazu tun müssen. Aufrufe der Methode paint() beispielsweise werden vom Browser erzeugt und verarbeitet - Sie müssen nur sagen, was gezeichnet werden soll. Einige Ereignisse jedoch, wie etwa ein Mausklick innerhalb Ihres Applets, müssen explizit verarbeitet werden, indem Code in einer Methode zur Ereignisverarbeitung geschrieben wird. Wenn Sie eigene Java-Programme schreiben, um diese Art von Ereignissen zu verarbeiten, können Sie Eingaben vom Anwender ermitteln und Ihr Programm kann basierend auf dieser Eingabe sein Verhalten ändern.
Mausereignisse gibt es in zwei grundlegenden Varianten, Mausklicks und Mausbewegungen.
Mausklick-Ereignisse treten auf, wenn ein Anwender eine der Maustasten drückt oder losläßt;
Mausbewegungs-Ereignisse treten void this_mouseClicked(MouseEvent e) {...}
Alle Mausereignisse haben als Argument ein Objekt des Typs MouseEvent, dessen
Konstruktormethonen-Header wie folgt aussieht:
public MouseEvent(Component source, int id, long when, Der Parameter source ist das Objekt, das das Ereignis ausgelöst hat, etwa eine Schaltfläche oder ein
Menüeintrag. Der Parameter id gibt an, welches Mausereignis stattgefunden hat (int-Konstanten:
MOUSE_CLICKED, MOUSE_PRESSED, MOUSE_RELEASED, MOUSE_MOVED,
MOUSE_ENTERED, MOUSE_EXITED oder MOUSE_DRAGGED). Jedes Ereignis hat einen
eindeutigen Zeitstempel. Der Modifier-Parameter gibt an, ob eine der Modifier-Tasten gedrückt wurde
(Shift, Alt oder Strg), als das Mausereignis stattfand. Die Parameter x und y gben die x,y-Koordinaten des
Mausereignisses relativ zur Quellkomponente an. clickCount gibt an, wie viele Klicks stattgefunden haben.
Ein Doppelklick beispielsweise würde einen clickCount von 2 erzeugen. Der Parameter popupTrigger ist
true, wenn das Mausereignis ein Popup-Menü auf der Plattform verursacht hat, etwa ein Klick mit der
rechten Maustaste in der Windows-Umgebung.
Dem MouseEvent-Objekt sind mehrere Methoden zugeordnet, die Ihnen Zugriff auf seine nicht-öffentlichen
Instanzvariablen bieten:
Mit diesen Methoden ermitteln Sie Informationen über die MouseEvent-Instaznz in Ihren Methoden zur
Verarbeitung des Mausereignisss. Weil der Standard-Ereignis-Handler, der vom JBuilder erzeugt wird, das
MouseEvent als e bezeichnet, können Sie diese Methoden als e.getX() oder e.getClickCount() ansprechen.
in your event handler
Mausklick-Ereignisse treten auf, wenn ein Anwender irgendwo auf Ihrem Applet oder in einem der Fenster
Ihrer Anwendung eine Maustaste drückt. Sie können Mausklicks auffangen, um einfache Dinge auszuführen
- den Sound im Applet ein- oder ausschalten, in einer Präsentation zum nächsten Bild weiterschalten oder
den Bildschirm löschen und neu beginnen. Sie können die Mausklicks aber auch in Kombination mit
Mausbewegungen betrachten, um komplexere Aktionen in Ihrem Programm auszuführen.
Wenn Sie mit der Maus klicken, werden mehrere Ereignisse erzeugt. Das mouseClicked-Ereignis zeigt, daß
die Maus gedrückt und losgelassen wurde. Aber was ist, wenn Sie zwischen dem Drücken und dem
Loslassen der Maustaste unterscheiden wollen? Betrachten Sie beispielsweise ein Pulldown-Menü. Wenn
Sie die Maustaste drücken, wird das Menü aufgeklappt, wenn Sie sie loslassen, wird ein Menüeintrag
ausgewählt. Wenn Sie nur ein Ereignis für beides hätten, könnten Sie eine solche Verwendung nicht
implementieren. Neben dem mouseClicked-Ereignis erzeugt das Klicken mit der Maus also auch ein
mousePressed-Ereignis.
Hier folgen drei einfache Button-Ereignis-Handler, die Koordinaten-Informationen ausgeben, wenn die
Ereignisse mouseClicked, mousePressed oder mouseReleased auftreten:
void button1_mouseClicked(MouseEvent e) { Um den Handler zu erzeugen, selektieren Sie das Ereignis auf der Ereignis-Registerkarte. Klicken Sie auf
die rechte Spalte, um den Handler anzugeben, und dann doppelklicken Sie, um den Methodenheader zu
erzeugen (Sie können auch dreimal klicken, um diese beiden Schritte zusammenzufassen). Jetzt fügen Sie die
beiden folgenden Codezeilen für die Methoden ein. Beachten Sie, daß die MouseEvent-Instanzvariablen
nicht öffentlich sind un nur über die MouseEvent-Methoden zur Verfügung stehen.
Wenn Sie das ausprobieren, sehen Sie, daß für einen einfachen Mausklick drei Zeilen ausgegeben werden:
A mousePressed event occurred at 31,5 Das scheint ganz einfach zu sein: Die Maustaste wird gedrückt, wird freigegeben und der Mausklick ist
abgeschlossen. Wenn Sie Klicken und Ziehen, bevor Sie loslassen, werden nur zwei Zeilen ausgegeben:
A mousePressed event occurred at 9,8 Warum kein Mausklick? Das System weiß, daß etwas passiert ist (die Maus wurde gezogen), während die
Maustaste gedrückt und losgelassen wurde, deshalb kann es die beiden nicht zu einem einfachen Mausklick
auflösen und es wird kein mouseClicked-Ereignis erzeugt.
In diesem Abschnitt erzeugen Sie ein Applet, das das mousePressed-Ereignis verarbeitet. Es beginnt mit
einem leeren Bildschirm und wartet. Wenn Sie auf den Bildschirm klicken, wird ein blauer Punkt gezeichnet.
Wir erzeugen das grundlegende Applet mit dem Applet-Experten. Bei geöffnetem Projekt
HandlingEvents.jpg wählen Sie Datei | Neu und doppelklicken auf das Applet-Objekt. Wenn der erste
Dialog des Applet-Experten erscheint, löschen Sie den Text im Package-Feld und geben in das
Klasse-Feld Spots ein. Anschließend klicken Sie auf die Schaltfläche Fertigstellen. Dadurch wird ein
Code-Gerüst für das Applet Spots.java erzeugt, ebenso wie die Datei Spots.html, mit der Sie Ihr Applet
testen.
Klicken Sie im Struktur-Feld auf den Applet-Knoten (direkt unterhalb des Spots-Knotens), wodurch die
Klassendeklaration von Spots markiert wird. Fügen Sie die folgenden Codezielen in den Inhalts-Bereich ein:
Dieser Code definiert die beiden Instanzvariablen der Klasse: die x- und y-Koordinaten, an der der aktuelle
Punkt gezeichnet wird.
Jetzt wollen Sie die background-Eigenschaft für das Applet auf white setzen. Klicken Sie auf die
Design-Registerkarte, um den AppBrowser in den Visual-Design-Modus zu versetzen. Das this-Objekt
sollte selektiert werden; es stellt den Zeichenbereich Ihres Applets dar. Klicken Sie auf die
Eigenschaften-Registerkarte des Inspektors, doppelklicken Sie auf die background-Eigenschaft und klicken
Sie auf die Schaltfläche mit den drei Punkten, um den background-Dialog anzuzeigen. Klikken Sie auf den
Dropdown-Pfeil im Auswahlfeld oben im Dialog und scrollen Sie nach oben, um White auszuwählen.
Klicken Sie auf OK. Wenn Sie jetzt den Quellcode betrachten, sehen Sie, daß in der jbInit()-Methode eine
neue Codezeile eingefügt wurde:
this.setBackground(Color.white);
Sie wollen hier die background-Eigenschaft setzen, und nicht in der paint()-Methode, weil paint() bei jedem
neuen Hinzufügen eines Punkts aufgerufen wird. Weil Sie den Hintergrund nur einmal setzen müssen, würde
das Setzen in der paint()-Methode das Ganze nur unnötig verlangsamen. Die hier gewählte Einstellung
verbessert die Performance.
Die wichtigste Aktion dieses Applets erfolgt in der Methode mousePressed(). Um den Ereignis-Handler
einzufügen, klicken Sie auf die Ereignis-Registerkarte des Inspektors. Jetzt klicken Sie dreimal in die rechte
Spalte des Ereignisses mousePressed, um den Methodenheader in Ihrem Quellcode zu plazieren. Fügen Sie
die foglenden Zeilen in seinen Rumpf ein:
x = e.getX(); Wenn ein Mausklick erfolgt, setzt die Methode mousePressed() die Variablen x und y auf die von den
Methoden getX() und getY() zurückgegebenen x- und y-Variablen. Anschließend wird die
repaint()-Methode aufgerufen.
Sie müssen auch die update()-Methode überschreiben, um den internen Aufruf von repaint() zu eliminieren:
public void update(Graphics g) { Dies ist keine Animation, warum also update() überschreiben? Wenn nicht, müßten Sie alle bereits
vorhandenen Punkte und den aktuellen Punkt verwalten, so daß Sie sie neuzeichnen könnten, nachdem der
interne Aufruf von repaint() in update() den Bildschirm Ihres Applets gelöscht hätte.
In Ihrer paint()-Methode könnten Sie in Reaktion auf Ihren Aufruf von repaint() im mousePressed-Ereignis
die Punkte neu zeichnen:
public void paint(Graphics g) { Weil der Ursprung die obere linke Ecke des umschließenden Rechtecks ist, zeichnen Sie in dieser
paint()-Methode den aktuellen Punkt ein bißchen weiter oben und links, so daß der Punkt um den Hotspot
des Mauscursors gezeichnet wird, und nicht unterhalb und rechts davon. Listing 12.1 zeigt den Code für das
Applet Spots.
1: import java.awt.*; Das ist alles, was Sie brauchen,um ein Applet zu erzeugen, das Mausklicks verarbeitet. Alles andere wird
Ihnen abgenommen. Abbildung 12. 1 zeigt das Spots-Applet im appeltviewer, nachdem einige Punkte
gezeichnet wurden.
Abbildung 12.1: Das Applet Spots
Um den Zeichenbereich zu löschen, minmieren Sie das appletviewer-Fenster und stellen es wieder her,um
das Applet neu zu starten.
Immer wenn die Maus bewegt wird, werden Maus-Ereignisse erzeugt. Wie viele Ereignisse erzeugt werden,
hängt von der Art der Mausbewegung ab:
Betrachten Sie die folgenden vier Ereignis-Handler, die auf diesen Ereignissen basieren:
void button1_mouseMoved(MouseEvent e) { Wenn Sie ein Applet mit diesen Ereignis-Handlern ausführen, sehen Sie, daß für eine Mausbewegung von
fünf Pixeln fünf mouseMoved-Ereignisse erzeugt werden, eines für jedes Pixel, über das die Maus bewegt
wird:
A mouseMoved event occurred at 31,5
A mousePressed event occurred at 48,7
A mouseEntered event occurred at 112,78 Alle bisher gezeigten Beispiele sezten voraus, daß Sie die Maus langsam und gleichmäßig passieren. Was
passiert, wenn Sie sie schnell über eine Komponente schieben? Kann das System wirklich jedes Pixel
erkennen? Hier die Ausgabe, die entsteht, wenn die Komponente button1 schnell überquert wird:
A mouseEntered event occurred at 133,89 Beispiele verdeutlichen vieles. In diesem Abschnitt entwickeln Sie ein Applet, mit dem Sie 10 gerade Linien
auf dem Bildschirm zeichnen können, indem Sie die Maus von einem Anfangspunkt zu einem Endpunkt
verschieben. Abbildung 12.2 zeigt das Applet Lines.
Abbildung 12.2: Das Applet Lines
Wählen Sie bei geöffnetem HandlingEvents.jpr -Projekt in der IDE Datei | Neu und doppelklicken Sie auf
das Applet-Objekt. Wenn der erste Schritt des Applet-Experten erscheint, löschen Sie den Text im
Packages-Feld und geben in das Klasse-Feld Lines ein. Klicken Sie auf die Schaltfläche Fertigstellen.
Jetzt wird das Code-Gerüst für das Applet Lines.java erzeugt, ebenso wie die HTML-Datei Lines.html.
Klicken Sie im Struktur-Feld auf de Applet-Knoten (unterhalb von Lines), so daß die Klassendeklaration
hervorgehoben dargestellt wird. Fügen Sie die folgenden Codezeilen unterhalb dieser Zeile im
Inhalts-Bereich ein:
int MAXLINES = 10; Dieser Code definiert die Instanzvariablen der Klasse Lines:
Jetzt klicken Sie auf die Design-Registerkarte des AppBrowsers, klicken auf die Eigenschaften-Seite des
Inspektors und setzen die background-Eigenschaft auf pink, so daß die folgende Codezeile in der
jbInit()-Methode erzeugt wird:
this.setBackground(Color.pink);
Die drei wichtigsten Ereignisse in diesem Applet sind mousePressed, das den Ankerpunkt für die aktuelle
Linie setzt, mouseDragged, das die aktuelle Linie zeichnet, und mouseReleased, das den Endpunkt für die
neue Linie setzt. Mit den eben erzeugten Instanzvariablen ist es nur noch erforderlich, die richtigen Variablen
in die richtigen Methoden einzugeben, und zu prüfen, ob MAXLINES bereits überschritten ist.
Klicken Sie auf die Design-Registerkarte, dann auf die Ereignisse-Registerkarte des Inspektors, und klicken
Sie dreimal auf die rechte Spalte von mousePressed, um den Methodenheader in Ihren Quellcode
einzufügen. Schreiben Sie die folgenden Zeilen in den Rumpf:
if (currLine <= MAXLINES) Wenn der Mausklick auftritt, setzt mousePressed() das Point-Objekt anchor auf die x- und y-Variablen, die
von getX() und getY() zurückgegeben wurden.
Jetzt wollen Sie einen Gummiband-Effekt realisieren, so daß die Linie beim Zeichnen der Maus folgt.
Klicken Sie auf die Design-Registerkarte, um in de Design-Modus zu wechseln, klicken Sie dreimal auf das
Ereignis mouseDragged und fügen Sie den folgenden Code in die Methode ein:
if (currLine <= MAXLINES) { Das mouseDragged-Ereignis enthält den aktuellen Punkt, wenn die Maus gezogen wird, deshalb verwenden
Sie diesen Ereignis-Handler, um den aktuellen Punkt zu verfolgen und ihn für jede Bewegung neu zu
zeichnen, so daß die Linie animiert erscheint.
Anfangs- und Endpunkt der neuen Linie werden erst in die Arrays eingetragen, wenn die Maustaste
losgelassen wird. Das erfolgt in der Methode addLine(). Klicken Sie auf die Design-Registerkarte, klicken
Sie dreimal auf mouseReleased und fügen Sie den folgenden Code ein:
if (currLine <= MAXLINES) Wenn Sie die maximale Anzahl Zeien erreicht haben, sehen Sie die weiße Linie, wenn Sie zeichnen, aber sie
wird der aktuellen Liste der Linien nicht mehr hinzugefügt. Hier die addLine()-Methode, die Sie nach der
mouseReleased()-Methode einfügen können:
void addLine(int x, int y) { Beim Zeichnen des Applets werden alle alten Linien gezeichnet, deren Endpunkte und Anfangspunkte in den
Arrays starts und ends gespeichert sind, ebenso wie der aktuellen Linie, deren Anfangs- und Endpunkte in
anchor und currPoint abgelegt sind. Um die Animation der aktuellen Linie anzuzeigen, zeichnen Sie sie weiß.
Hier die paint()-Methode (fügen Sie diesen Code unterhalb der Methode addLine() ein):
public void paint(Graphics g) { In der paint()-Methode wird beim Zeichnen der aktuellen Linie neben der Überprüfung von MAXLINES
geprüft, ob currPoint gleich null ist. Wenn das der Fall ist, zeichnet das Applet gerade keine Linie und es gibt
keinen Grund, es neu zu zeichnen. Durch einen Test auf currPoint können Sie genau das zeichnen, was Sie
brauchen. Durch Einfügen einiger weniger Codezeilen in den Ereignis-Handlern und einiger grundlegender
Methoden haben Sie damit ein erstes Zeichen-Applet. Listing 12.2 zeigt den Code für das Applet Lines.
1: import java.awt.*; In der Elternklasse von MouseEvent, InputEvent, sind drei modifier-Variablen definiert, die sich
insbesondere auf Mausereignisse beziehen. Es handelt sich dabei um BUTTON1_MASK,
BUTTON2_MASK und BUTTON3_MASK. Weil diese Konstanten als int-Werte gespeichert sind,
können Sie sie in einer switch-Anweisung vewrenden, nachdem Sie den Wert durch Aufruf von
getModifiers() ermittelt haben, die auch von InputEvent geerbt wurde.
switch (e.getModifiers()) { Wenn Sie das Drücken der Tasten nicht explizit verarbeiten, wird die linke Maustaste vorausgesetzt. Neben
diesen mausbezogenen Konstanten gibt es noch vier weitere Konstanten: ALT_MASK, CTRL_MASK,
META_MASK und SHIFT_MASK. Um auf diese Modifier-Tasten zu prüfen, verwenden Sie die
Booleschen Methoden isAltDown(), isCtrlDown(), isMetaDown() und isShiftDown() (ebenfalls in
InputEvent definiert). Die letzten vier Modifierkönnen auch für Tastatur-Ereignisse verwendet werden.
Tastaturereignisse werden erzeugt, wenn der Anwender eine Taste oder eine Tastenkombination drückt. Mit
Hilfe der Tastaturereignisse können Sie die Werte der gedrückten Tasten ermitteln, um eine entsprechende
Aktion vorzunehmen, oder einfach Zeicheneingaben von den Anwendern Ihres Programms
entgegenzunehmen.
Die Verarbeitung von Tastaturereignissen ist so einfach wie die Verarbeitung von Mausereignissen. Sie
müssen einfach nur die entsprechenden Ereignis-Handler erzeugen. Der Methodenheader, der in Ihren
Quellcode eingefügt wird, könnte wie folgt aussehen:
void textField1_keyPressed(KeyEvent e) {...}
Alle Tastaturereignisse haben als Argument ein Objekt vom Typ KeyEvent, dessen
Konstruktormethodenheader so aussehen könnte:
public KeyEvent(Component source, int id, long when, Der Parameter source ist das Objekt, das das Ereignis ausgelöst hat, etwa ein TextField oder ein TextArea.
Der Parameter id gibt an, welche Art Ereignis aufgetreten ist (int-Kosntanten: KEY_PRESSED,
KEY_RELEASED oder KEY_TYPED). Jedes Ereignis hat einen eindeutigen when-Zeitstempel. Der
modifiers-Parameter gibt an, ob eine oder mehrere Modifier-Tasten (Shift, Alt oder Strg) gedrückt waren,
als das Tastaturereignis stattgefunden hat. Der keyCode ist der ASCII-Wert der Taste, keyChar ist das
Unicode-Zeichen für die Taste.
Die Klasse KeyEvent definiert Methoden, die Ihnen Zugriff auf ihre nicht-öffentlichen Instanzvariablen gibt:
Diese Methoden können in Ihren Methoden zur Ereignisverarbeitung verwendet werden, um die
instantiierten Variablen zu verwnden, wenn ein KeyEvent auftritt. Wie das MouseEvent benennt JBuilder
das KeyEvent standardmäßig ebenfalls mit dem Bezeichner e, sie können also in Ihrem Ereignis-Handler als
e.getKexCode() oder e.getKeyChar()auf diese Methoden zugreifen.
Wie Sie aus diesen Methodenüberblicken sehen, ist die keyCode-Variable als Integer definiert. Weil dieser
Wert als Integer abgelegt wird, kann er in einer switch-Anweisung verwwendet werden, so wie die bereits
beschriebenen modifier. Tabelle 12.1 bietet einen kurzen Überblick über die häufigsten
keyCode-Konstanten.
Tabelle 12.1: keyCode-Konstanten
[Wird zurückgegeben, wenn es kein entsprechendes
Unicode-Zeichen gibt] VK_NUM_LOCK Eine vollständige Liste finden Sie in den Java-Hilfedateien unter dem Thema java.awt.event.KeyEvent
Es gibt drei Ereignisse, um Tastendrücke aufzufangen, die denen für Mausklicks entsprechen: keyPressed,
keyReleased und keyTyped. Hier folgen drei einfache TextArea-Ereignis-Handler, die das Ereignis und
keyText für jedes Ereignis ausgeben, wozu die Methoden getKeyCode() und getKeyText() verwendet
werden.
void textArea1_keyPressed(KeyEvent e) { Wenn Sie das ausprobieren, sehen Sie, daß bei jedem drücken einer Zeichen-Taste alle drei Ereignisse
erzeugt werden: zuerst ein keyPressed-Ereignis, gefolgt von einem keyTyped-Ereignis und einem
keyReleased-Ereignis.
A keyPressed event occurred. Wenn das Drücken einer Taste immer ein keyPressed- und ein keyReleased-Ereignis erzeugt, warum
werden dann zwei separate Ereignisse verwendet? Das wird so genhandhabt, damit Sie die Reihenfolge der
Tasten in Tastenkombinationen ermitteln können. Angenommen, Sie wollen einen Textblock in einem
Texteditor-Applet einrücken, indem Sie die Tastenkombination Strg+B+I drücken. Ihr Applet fordert
jedoch, daß di Strg-Taste gedrückt bleibt, während B und I gedrückt werden, weil Strg+B eine andere
Aktion bewirken würde. Angenommen, im Applet ist ein Textblock selektiert, dann würde das wie folgt
ablaufen:
Wenn diese sechs Ereignisse nicht in dieser Reihenfolge auftreten, wird nichts ausgeführt. Und das passiert,
wenn Sie die folgende Tastensequenz in ein Programm mit unseren Testmethoden eingeben:
A keyPressed event occurred. Dieser Abschnitt betrachtet ein Applet, das Tastaturereignisse verarbeitet. Es ermöglicht Ihnen, ein Zeichen
einzugeben, und zeigt dieses Zeichen in der Mitte des Applet-Fensters an. Sie können dieses Zeichen mit
Hilfe der Pfeiltasten auch auf dem Bildschirm verschieben. Die Eingabe eines neuen Zeichens starten Sie den
Vorgang von Neuem.
Dieses Applet ist weniger kompliziert als die zuvor entwickelten Ereignisse, weil nur ein
keyPressed-Ereignis-Handler, eine paint()-Methode, zwei Additionen in der init()-Methode und zwei
Eigenschaftseinstellungen erforderlich sind.
Wählen Sie bei geöffnetem Projekt HandlingEvents.jpr in der IDE Datei | Neu und doppelklicken Sie auf
das Applet-Objekt. Im ersten Schritt des Applet-Experten löschen Sie den Text im Package-Feld und
geben in das Klasse-Feld KeyTest ein. Dadurch erzeugen Sie das Gerüst für das Applet KeyTest.java
sowie ine KeyTest.html-Datei. Fügen Sie die folgenden Zeilen in die KeyTest-Klassendeklaration ein:
char currKey = 'A'; Dieser Code definiert die Instanzvariablen der Klasse KeyTest: currKey verfolgt, wenn sich das Zeichen
ändert (initialisiert mit A), und currX und currY geben die x,y-Koordinaten des Zeichens an.
Jetzt klicken Sie auf die Design-Registerkarte im AppBrowser, dann auf die Eigenschaften-Registerkarte im
Inspektor und setzen die background-Eigenschaft auf Green. Doppelklicken Sie auf die font-Eigenschaft
und dann auf die Schaltfläche mit den drei Punkten, um den font-Dialog anzuzeigen. Wählen Sie Helvetica,
Fett und 36 und klicken Sie auf OK. Diese Eigenschafts-Einstellungen erzeugen die folgenden beiden
Codezeilen in der Methode jbInit():
this.setFont(new Font("Helvetica", 1, 36)); Jetzt müssen Sie die nächste Codezeile an das Ende der jbInit()-Methode eingeben, so daß Ihr Applet die
Tastencodes auffängt:
Klicken Sie auf die Quelltext-Registerkarte, um in den Projekt-Browser-Modus zu gehen, und setzen Sie
die Anfangsposition für das Zeichen (etwa in der Mitte des Bildschirms), indem Sie am Ende der
init()-Methode die folgenden Zeilen ein:
currX = (getSize().width / 2); Weil das Verhalten dieses Applets auf der Tastatureingabe basiert, erfolgt ein Großteil der Arbeit im
keyPressed-Ereignis-Handler. Klicken Sie auf die Design-Registerkarte und klicken Sie dreimal auf das
keyPressed-Ereignis, um den Methodenheader einzufügen und die folgenden Codezeilen einzutragen:
switch (e.getKeyCode()) { Dadurch wird die Zeichenposition bei jedem Drücken einer Pfeiltaste um fünf Pixel verschoben und das
Zeichen wird geändert, wenn eine andere Taste gedrückt wird. Tasten, die keine Zeichen und keine
Pfeilrichtungen darstellen, werden ignoriert. Jetzt erzeugen wir noch die paint()-Methode, die ganz einfach
ist:
public void paint(Graphics g) { Sie gibt einfach das aktuelle Zeichen an der aktuellen Position aus. Listing 12.3 zeigt den Code für KeyTest.
1: import java.awt.*; Neben Tastatur- und Mausereignissen bietet der AWT mehrere Standardereignisse, auf die Sie auf Ihrer
Oberfläche reagieren können. Die meisten der Ereignis-Handler für diese Ereignisse können über die
Ereignisse-Registerkarte des Inspektors gesetzt werden, so wie schon für Maus- und Tastaturereignisse.
Abbildung 12.3 zeigt einen Teil der Hierarchie der Klasse java.awt.AWTEvent, die den Kategorien
entsprechen, in die diese Ereignisse eingeteilt werden können.
Abbildung 12.3: Unterklassen von AWTEvent
Wie Sie sehen, bilden die InputEvent-Unterklassen nur einen kleinen Teil der AWTEvent-Hierarchie. In den
folgenden Abschnitten erfahren Sie, welche Ereignis-Handler im JBuilder den Ereignissen dieser
Unterklassen-Kategorien entsprechen. Die in diesen Unterklassen definierten Methodeen werden ebenfalls
vorgestellt, aber beachten Sie, daß jede Unterklasse von ihrer Oberklasse erbt. Auch hier benennt JBuilder
das Ereignis standardmäßig als e, Sie können also beispielsweise auf die Methode getModifiers() als
e.getModifiers() zugreifen.
Eine vollständige Beschreibung dieser Klasse und ihrer Methoden finden Sie in der Online-Hilfe von Java.
Benutzeroberflächen-Komponenten erzeugen ein spezielles Ereignis, das sogenannte Aktionsereignise. In
JBuilder wird eine Aktion einer Benutzeroberflächen-Komponente aufgefangen, indem der
actionPerformed-Ereignis-Handler definiert wird. Hier der Methodenheader für einen
actionPerformed-Ereignis-Handler, beispielsweise für die Komponente myButton:
void myButton_actionPerformed(ActionEvent e) {...}
Diese Ereignis-Handler nehmen ein ActionEvent-Objekt als Argument entgegen. Hier der Header der
Konstruktormethode:
public ActionEvent(Object source, int id, source ist das Objekt der Benutzeroberflächen-Komponente, das das Ereignis ausgelöst hat. id gibt den
Typ der Aktion an (int-Konstante: ACTION_PERFORMED). modifiers gibt an, ob eine oder mehrere
Modifier-Tasten gedrückt waren, als das Ereignis aufgetreten ist. Der command-Parameter ist der Wert der
actionCommand-Eigenschaft der Komponente:
Das ActionEvent-Objekt hat die folgenden Methoden:
Angenommen, Sie wollen ein einfaches Applet mit sechs Schaltflächen mit den Farben des Regenbogens
anlegen. Sie könnten für jede Schaltfläche einen eigenen Ereignis-Handler anlegen, aber in diesem Beispiel
erzeugen Sie den actionPerformed()-Ereignis-Handler für die erste Schaltfläche und verwendendiesen auch
für die anderen fünf Schaltflächen. Im Ereignis-Handler wird die Hintergrundfarbe des Applets geändert, je
nachdem, welche Schaltfläche angeklickt wurde.
Fügen Sie dem heutigen Projekt das neue Applet ActionTest hinzu. Ändern Sie im Desig-Modus bei
selektiertem this die background-Eigenschaft auf Gray, die layout-Eigenschaft auf FlowLayout und fügen Sie
sechs Button-Komponenten ein. Abbildung 12.4 zeigt die Benutzeroberfläche des Applets.
Abbildung 12.4: Das Applet ActionTest
Selektieren Sie button1 und ändern Sie seine <name>-Eigenschaft auf redBtn, seine label-Eigenschaft auf
Red. Beachten Sie, daß sich mit dem Bestätigen der label-Eigenschaft auch die actionCommand-Eigenschaft
auf Red ändert. Standardmäßig ist das actionCommand für eine Button-Komponente dasselbe wie ihre
label-Eigenschaft. Dadurch wird es einfach, mit der Methode getActionCommand() zu prüfen, welche
Schaltfläche gedrückt wurde.
Klicken Sie die einzelnen Schaltflächen nacheinander an und ändern Sie die <name> und
label-Eigenschaften wie in Tabelle 12.2 gezeigt.
Tabelle 12.2: Eigenschaften für das Abbildung ActionTest
Um den Ereignis-Handler für diese sechs Schaltflächen zu erzeugen, selektieren Sie die Komponente redBtn
und klicken auf die Ereignisse-Registerkarte. Wenn Sie jetzt dreimal auf einen Handler klicken, erhält er den
Namen redBtn_actionPeformed, abhängig von der selektierten Komponente. Aber Sie wollen einen
Ereignis-Handler erzeugen, der für alle sechs Schaltflächen eingesetzt werden kann, Sie sollten ihm also
einen generischeren Namen geben. Dazu klikken Sie auf das actionPerformed-JBuilder, das
redBtn_actionPerformed als Methodennamen vorschlägt. Drücken Sie Home, um den Cursor an den
Anfang des Methodennamens zu setzen, und ändern Sie red in color. Jetzt doppelklicken Sie, um den
Methodenheader im Quellcode zu erzeugen.
In diesem Ereignis-Handler wollen Sie wissen, welche Schaltfläche das Ereignis ausgelöst hat. Durch
Auswertung des von getActionCommand() zurückgegebenen Strings können Sie den Hintergrund des
Applets auf die entsprechende Farbe setzen und es dann neuzeichnen. Weil die Methode einen String und
keinen elementaren Datentyp zurückgibt, brauchen Sie verschachtelte if-else-Anweisungen statt eines
switch. Hier folgt der Rumpf des Ereignis-Handlers colorBtn_actionPerformed():
String btnColor = e.getActionCommand(); Immer wenn Sie auf eine der sechs Schaltflächen in diesem Applet klicken, wird der gemeinsam genutzte
Ereignis-Handler ausgeführt und die Zeichenfläche des Applets ändert die Farbe. Listing 12.4 zeigt das
Applet ActionTest.
1: import java.awt.*; MenuBar- und PopupMenu-Komponenten verwenden ebenfalls die label-Eigenschaft, um den
Standard-actionCommand-Wert zu setzen. Detaillierte Informationen über die actionCommand-Werte für
anderen AWT-Komponenten finden Sie in der Online-Dokumentation.
Das Ereignis adjustmentValueChanged ist im AWT für das Inkrement und Dekrement veränderbarer
Objekte definiert, wie etwa Scrollbar. Der Methodenheader für einen
adjustmentValueChanged-Ereignis-Handler könnte wie folgt aussehen:
void scrollbar1_adjustmentValueChanged(AdjustmentEvent e) {...}
Diese Ereignis-Handler nehmen ein AdjustmentEvent-Objekt entgegen. Hier der Header der
Konstruktormethode:
public AdjustmentEvent(Adjustable source, int id, source ist die Komponente, die das Ereignis ausgelöst hat. id stellt den Typ der Anpassung dar
(int-Konstante: ADJUSTMENT_VALUE_CHANGED). type gibt an, welche Anpassung in dem Ereignis
aufgetreten ist, dabei kann eine von fünf Konstanten verwendet werden: UNIT_INCREMENT,
UNIT_DECREMENT, BLOCK_INCREMENT, BLOCK_DECREMENT oder TRACK. value ist ein
Integer, der die Einheit angibt, die für die Anpassung verwendet wird.
Das AdjustmentEvent-Objekt hat die folgenden Methoden:
Um dieses Ereignis zu beobachten, erzeugen Sie das Applet ScrollTest. Fügen Sie ein Label und ein
Scrollbar ein und ändern Sie die Eigenschaften wie in Tabelle 12.3 gezeigt.
Tabelle 12.3: Eigenschaften für das Applet ScrollTest
Wenn Sie fertig sind, klicken Sie auf valueSbar, klicken auf die Ereignisse-Seite und klicken dreimal auf das
Ereignis adjustmentValueChanged. Jetzt fügen Sie der Methode in Ihrem Quellcode die folgenden Zeilen
hinzu:
int v = e.getValue(); Die erste Zeile ermittelt den Wert der Anpassung aus dem AdjustmentEvent-Objekt. Die zweite Zeile setzt
die value-Eigenschaft der valueSbar-Komponente. Die dritte Zeile setzt den Text von valueLbl auf die
Stringdarstellung dieses Werts. Wenn Sie das Applet ScrollTest ausführen, wird der aktuelle Wert des
Schiebereglers in valueLbl reflektiert, wie in Abbildung 12.5 gezeigt.
Abbildung 12.5: Das Applet ScrollTest
Den vollständigen Quellcode für ScrollTest finden Sie in Listing 12.5.
1: import java.awt.*; Komponentenereignisse sind im AWT definiert, so daß Sie erkennen können, ob eine Komponente
verborgen, angezeigt, verschoben oder in der Größe verändert wurde. Der AWT verarbeitet das
Verschieben, Größenändern und Anzeigen von Komponenten automatisch, aber es gibt Situationen, wo Sie
basierend auf diesen Ereignisen eine zuästzliche Funktionalität einfügen wollen. Der Konstruktor
ComponentEvent ist einfach:
public ComponentEvent(Component source, int id)
Er gibt die Quelle des Ereignisses an, source, sowie seine ID (int-Konstanten: COMPONENT_HIDDEN,
COMPONENT_MOVED, COMPONENT_RESIZED, COMPONENT_SHOWN). Er hat eine
getComponent()-Methode, die das Objekt zurückgibt, das das Ereignis erzeugt hat (den Wert des
source-Parameters).
Alle Komponenten haben diese vier Ereignisse auf ihrer Ereignisse-Seite: componentHidden,
componentMoved, componentResized und componentShown, die den id-Parameter-Konstanten des
ComponentEvent-Objekts entsprechen. Wenn Sie ich Ihrem Quellcode einen Ereignis-Handler einfügen,
sieht die Methodensignatur wie folgt aus:
void textarea1_ComponentResized(ComponentEvent e) {...}
Auch hier können Sie auf die ComponentEvent-Methoden zureifen, indem Sie die Syntax
e.methodenName anwenden.
Fokusereignisse sind im AWT definiert, damit Sie erkennen können, ob eine Komponente den Fokus
erhalten hat (also die aktive Komponente ist), oder ob sie den Fokus verloren hat. Hier der Konstruktor
FocusEvent:
public FocusEvent(Component source, int id, Er gibt die Quelle des Ereignisses an, source, sowie seine id (int-Konstanten: FOCUS_GAINED und
FOCUS_LOST). Darüber hinaus gibt es den temporary-Parameter, der angibt, ob das FocusEvent ein
temporärer Wechsel war, was auftritt, wenn Komponenten aufgrund anderer Operationen vorübergehend
den Fokus erhalten. Der permanente Fokus wird beispielsweise erteilt, wenn ein Anwender in einem Dialog
auf eine Komponente springt. Diese Ereignisklasse definiert eine isTemporary()-Methode, die true
zurückgibt, wenn FocusEvent temporär ist, false, wenn es permanent ist.
Die meisten Komponenten haben focusGained und focusLost auf ihrer Ereignisse-Seite, was den
id-Konstanten für das FocusEvent-Objekt entspricht. Wenn Sie in Ihrem Quellcode einen Ereignis-Handler
erzeugen, könnten die Methodensignatur wie folgt aussehen:
void checkbox1_focusGained(FocusEvent e) {...}
Auch auf die ComponentEvent-Methoden wird über die Syntax e.methodenName zugegriffen.
itemStateChanged ist im AWT definiert, damit Sie erkennen können, ob ein Element selektiert ist, etwa
Elemente in einer List- oder Choice-Komponente. Der Methodenheader für einen Ereignis-Handler einer
List-Komponente könnte wie folgt aussehen:
void list1_ itemStateChanged(ItemEvent e) {...}
Diese Ereignis-Handler nehmen als Argument ein ItemEvent-Objekt entgegen. Hier der Header der
Konstruktormethode:
public ItemEvent(ItemSelectable source, int id, source ist die Komponente, die das Ereignis ausgelöst hat. id ist eine Integer-Konstante,
ITEM_STATE_CHANGED, die dem Ereignis itemStateChanged entspricht. Der object-Parameter gibt an,
welches Element das Ereignis verursacht hat. Der stateChange-Parameter nimmt eine von zwei Konstanten
an: SELECTED oder DESELECTED. Die Methoden des ItemEvent-Objekts sind unter anderem:
Der Methodenzugriff erfolgt über die Syntax e.methodenName.
Fensterereignisse ermöglichen Ihnen, den aktuellen Status eines Frames auf Ihrer Benutzeroberfläche zu
ermitteln. Hier der WindowEvent-Konstruktor:
public WindowEvent(Window source, int id)
source ist die Quelle des Ereignisses, und die id des Ereignisses kann durch die folgenden
Integer-Konstanten dargestellt werden:
Diese Konstanten entsprechen den Frame-Ereignissen, windowActivated, windowClosed, windowClosing,
windowDeactivated, windowDeiconified, windowIconified und windowOpened. Diese Ereignisklasse
definiert eine getWindow()-Methode, die das in der Instanzvariablen source gespeicherte Fenster
zurückgibt.
Es ist ganz einfach, im JBuilder Ereignisse zu verarbeiten, weil die Ereignisse-Registerkarte des Inspektors
alle wichtigen Ereignisse für jede selektierte Komponente anzeigt. Wenn Sie dreimal auf das Ereignis
klicken, wird ein Methodenheader für Sie in de Code eingefügt, wo Sie Ihren Code einfügen können. Mit
dem Ereignis-Handler fängt das Programm automatisch die Ereignisse auf.
F Im Lines-Applet werden die Koordinaten für Startpunkt und Endpunkt in Arrays abgelegt, die eine
feste Größe haben. Kann ich das Applet so abändern, daß es unendlich viele Linien zeichnet?
A Verwenden Sie die Vector-Klasse. Vector ist Teil des java.util-Pakets und implementiert ein Array, das
automatisch anwächst - wie eine verkettete Liste in anderen Sprachen. Der Nachteil von Vector ist, daß seine
Elemente Objekte sein müssen. Das bedeutet, Sie müssen int-Werte in Integer-Objekte umwandeln, um sie in
den Vector einfügen zu können. Sie können die Elemente von Vector jedoch einfach über dessen Methoden
manipulieren. Wenn Sie ein Array variabler Größe brauchen, verwenden Sie Vector.
Der Workshop bietet zwei Möglichkeiten, zu überprüfen, was Sie in diesem Kapitel gelernt haben. Der
Quiz-Teil stellt Ihnen Fragen, die Ihnen helfen sollen, Ihr Verständnis für den vorgestellten Stoff zu vertiefen.
Die Antworten auf die Fragen finden Sie in Anhang A. Der Übungen-Teil ermöglicht Ihnen, Erfahrungen in
der Anwendung der Dinge zu sammeln, die Sie hier kennengelernt haben. Versuchen Sie, diese Dinge
durchzuarbeiten, bevor Sie mit der nächsten Lektion weitermachen.
int modifiers, int x, int y,
int clickCount, boolean popupTrigger)
Mausklicks
System.out.println("A mouseClicked event occurred at "
+ e.getX() + "," + e.getY());
}
void button1_mousePressed(MouseEvent e) {
System.out.println("A mousePressed event occurred at "
+ e.getX() + "," + e.getY());
}
void button1_mouseReleased(MouseEvent e) {
System.out.println("A mouseReleased event occurred at "
+ e.getX() + "," + e.getY());
}
A mouseReleased event occurred at 31,5
A mouseClicked event occurred at 31,5
A mouseReleased event occurred at 42,10
Das Spots-Applet
Diese Klasse muß in ihrer Klassendefinition nicht implements Runnable angeben. Wie Sie gleich
sehen werden, wenn Sie dieses Applet kompilieren, hat es auch keine run()-Methode. Warum nicht? Weil
es eigentlich nichts selbst macht - es wartet einfach nur auf Eingaben und reagiert darauf. Sie brauchen
keine Threads, wenn Ihr Applet nicht aktiv wird.
y = e.getY();
repaint();
Warum reagieren wir auf das mousePressed-Ereignis, und nicht auf mouseClicked? Sie müssen
sich nur um die Koordinaten kümmern, wo die Maustaste gedrückt wurde, und nicht, wo sie losgelassen
wurde. Betrachten Sie, was passiert, wenn ein Anwender ein wenig schwerfällig ist und klickt und die Maus
ein bißchen verschiebt, statt einen richtigen Mausklick zu erzeugen. Wenn Ihre Methode nur auf
mouseClicked reagiert, dann haben Sie Pech gehabt - weil die Maus verschoben wurde, werden nur ein
mousePressed- und ein mouseReleased-Ereignis erzeugt, und Ihre Methode reagiert nicht richtig. Durch
Reaktion auf mousePressed statt auf mouseClicked können Sie dieses Problem umgegen.
paint(g);
}
g.setColor(Color.blue);
g.fillOval(x - 10, y - 10, 20, 20);
}
2: import java.awt.event.*;
3: import java.applet.*;
4: import borland.jbcl.layout.*;
5: import borland.jbcl.control.*;
6:
7: public class Spots extends Applet {
8: int x;
9: int y;
10: XYLayout xYLayout1 = new XYLayout();
11: boolean isStandalone = false;
12:
13: //Get a parameter value
14: public String getParameter(String key, String def) {
15: return isStandalone ? System.getProperty(key, def) :
16: (getParameter(key) != null ? getParameter(key) : def);
17: }
18:
19: //Construct the applet
20: public Spots() {
21: }
22:
23: //Initialize the applet
24: public void init() {
25: try { jbInit(); } catch (Exception e) { e.printStackTrace(); }
26: }
27:
28: //Component initialization
29: public void jbInit() throws Exception{
30: this.addMouseListener(new Spots_this_mouseAdapter(this));
31: this.setBackground(Color.white);
32: xYLayout1.setWidth(400);
33: xYLayout1.setHeight(300);
34: this.setLayout(xYLayout1);
35: }
36:
37: //Get Applet information
38: public String getAppletInfo() {
39: return "Applet Information";
40: }
41:
42: //Get parameter info
43: public String[][] getParameterInfo() {
44: return null;
45: }
46:
47: void this_mousePressed(MouseEvent e) {
48: x = e.getX();
49: y = e.getY();
50: repaint();
51: }
52:
53: public void update(Graphics g) {
54: paint(g);
55: }
56:
57: public void paint(Graphics g) {
58: g.setColor(Color.blue);
59: g.fillOval(x - 10, y - 10, 20, 20);
60: }
61: }
62:
63: class Spots_this_mouseAdapter extends java.awt.event.MouseAdapter {
64: Spots adaptee;
65:
66: Spots_this_mouseAdapter(Spots adaptee) {
67: this.adaptee = adaptee;
68: }
69:
70: public void mousePressed(MouseEvent e) {
71: adaptee.this_mousePressed(e);
72: }
73: }
Mausbewegungen
System.out.println("A mouseMoved event occurred at "
+ e.getX() + "," + e.getY());
}
void button1_mouseDragged(MouseEvent e) {
System.out.println("A mouseDragged event occurred at "
+ e.getX() + "," + e.getY());
}
void button1_mouseEntered(MouseEvent e) {
System.out.println("A mouseEntered event occurred at "
+ e.getX() + "," + e.getY());
}
void button1_mouseExited(MouseEvent e) {
System.out.println("A mouseExited event occurred at "
+ e.getX() + "," + e.getY());
}
A mouseMoved event occurred at 31,6
A mouseMoved event occurred at 31,7
A mouseMoved event occurred at 31,8
A mouseMoved event occurred at 31,9
Ein Ziehen der Maus überfünf Pixel löst fünf mouseDragged -Ereignisse aus, eines für jedes Pixel.
Außerdem wird am Anfang und am Ende ein mousePressed -Ereignis erzeugt, so daß die Ausgabe für das
Ziehen der Maus über fünf Pixel wie folgt aussehen würde:
A mouseDragged event occurred at 46,7
A mouseDragged event occurred at 45,8
A mouseDragged event occurred at 44,8
A mouseDragged event occurred at 43,8
A mouseDragged event occurred at 42,8
A mouseReleased event occurred at 42,8
Immer wenn die Maus die Grenzen eines Objekts überschreitet, wird ein mouseEntered-Ereignis ausgelöst.
Wenn sie die Grenzen eines Objekts verläßt, wird ein mouseExited -Ereignis erzeugt. Eine langsame
vertikale Bewegung über unsere Beispiel-Komponente button1 würde die folgende Ausgabe erzeugen:
A mouseMoved event occurred at 16,0
A mouseMoved event occurred at 16,1
A mouseMoved event occurred at 16,2
A mouseMoved event occurred at 16,2
A mouseMoved event occurred at 16,3
A mouseMoved event occurred at 16,4
A mouseMoved event occurred at 16,5
A mouseMoved event occurred at 16,6
A mouseMoved event occurred at 16,7
A mouseMoved event occurred at 16,8
A mouseMoved event occurred at 16,9
A mouseMoved event occurred at 16,10
A mouseMoved event occurred at 16,11
A mouseMoved event occurred at 16,12
A mouseMoved event occurred at 16,13
A mouseMoved event occurred at 16,14
A mouseMoved event occurred at 16,15
A mouseMoved event occurred at 16,16
A mouseMoved event occurred at 16,17
A mouseMoved event occurred at 16,18
A mouseMoved event occurred at 16,19
A mouseMoved event occurred at 16,20
A mouseMoved event occurred at 16,21
A mouseMoved event occurred at 16,22
A mouseExited event occurred at 16,23
Und das für eine kleine Schaltfläche - stellen Sie sich vor, was passiert, wenn die Maus über ein Applet mit
400x300 Pixel gezogen wird! Beachten Se, daß das mouseEntered-Ereignis an der Stelle 112,78
aufgetreten ist, also nicht im Koordinatenraum der Schaltfläche. Die Eintrittskoordinaten sind die des
umschließenden Frames, wo die Maus den Frame verlassen hat und in die Komponente button1 eingetreten
ist. Die Verarbeitung der mouseEntered- und mouseExited-Ereignisse ist sinnvoll, wenn Sie den Mauscursor
ändern wollen, wenn er einen bestimmten Bereich des Bildschirms berührt, etwa wenn Sie wissen wollen,
wenn die Maus in den Luftraum Ihres Applet-Bildschirms eingetreten ist.
A mouseMoved event occurred at 38,11
A mouseExited event occurred at 38,29
Das zeigt, daß mouseMoved-Ereignisse in bestimmten Zeitabschnitten ermittelt werden, und nicht Pixel für
Pixel.
Das Applet Lines
Point starts[] = new Point[MAXLINES]; // Startpunkte
Point ends[] = new Point[MAXLINES]; // Endpunkte
Point anchor = null; // Anfang aktuelle Linie
Point currPoint = null; // Ende aktuelle Linie
int currLine = 0; // Anzahl Linien
anchor = new Point(e.getX(), e.getY());
currPoint = new Point(e.getX(), e.getY());
repaint();
}
addLine(e.getX(), e.getY());
starts[currLine] = anchor;
ends[currLine] = new Point(x, y);
currLine++;
currPoint = null;
repaint();
}
// draw existing lines
for (int i = 0; i < currLine; i++) {
g.drawLine(starts[i].x, starts[i].y, ends[i].x, ends[i].y);
}
// draw current line
g.setColor(Color.white);
if ((currLine <= MAXLINES) & (currPoint != null))
g.drawLine(anchor.x, anchor.y, currPoint.x, currPoint.y);
}
2: import java.awt.event.*;
3: import java.applet.*;
4: import borland.jbcl.layout.*;
5: import borland.jbcl.control.*;
6:
7: public class Lines extends Applet {
8: int MAXLINES = 10;
9: Point starts[] = new Point[MAXLINES]; // startpoints
10: Point ends[] = new Point[MAXLINES]; // endpoints
11: Point anchor = null; // start of current line
12: Point currPoint = null; // current end of line
13: int currLine = 0; // number of lines
14: XYLayout xYLayout1 = new XYLayout();
15: boolean isStandalone = false;
16:
17: //Construct the applet
18: public Lines() {
19: }
20:
21: //Initialize the applet
22: public void init() {
23: try { jbInit(); } catch (Exception e) { e.printStackTrace(); }
24: }
25:
26: //Component initialization
27: public void jbInit() throws Exception{
28: this.addMouseListener(new Lines_this_mouseAdapter(this));
29: this.addMouseMotionListener(new Lines_this_mouseMotionAdapter(this));
30: this.setBackground(Color.pink);
31: xYLayout1.setWidth(400);
32: xYLayout1.setHeight(300);
33: this.setLayout(xYLayout1);
34: }
35:
36: //Get Applet information
37: public String getAppletInfo() {
38: return "Applet Information";
39: }
40:
41: //Get parameter info
42: public String[][] getParameterInfo() {
43: return null;
44: }
45:
46: void this_mousePressed(MouseEvent e) {
47: if (currLine <= MAXLINES)
48: anchor = new Point(e.getX(), e.getY());
49: }
50:
51: void this_mouseDragged(MouseEvent e) {
52: if (currLine <= MAXLINES) {
53: currPoint = new Point(e.getX(), e.getY());
54: repaint();
55: }
56: }
57:
58: void this_mouseReleased(MouseEvent e) {
59: if (currLine <= MAXLINES)
60: addLine(e.getX(), e.getY());
61: }
62:
63: void addLine(int x, int y) {
64: starts[currLine] = anchor;
65: ends[currLine] = new Point(x, y);
66: currLine++;
67: currPoint = null;
68: repaint();
69: }
70:
71: public void paint(Graphics g) {
72:
73: // draw existing lines
74: for (int i = 0; i < currLine; i++) {
75: g.drawLine(starts[i].x, starts[i].y, ends[i].x, ends[i].y);
76: }
77:
78: // draw current line
79: g.setColor(Color.white);
80: if ((currLine <= MAXLINES) & (currPoint != null))
81: g.drawLine(anchor.x, anchor.y, currPoint.x, currPoint.y);
82: }
83: }
84:
85: class Lines_this_mouseAdapter extends java.awt.event.MouseAdapter {
86: Lines adaptee;
87:
88: Lines_this_mouseAdapter(Lines adaptee) {
89: this.adaptee = adaptee;
90: }
91:
92: public void mousePressed(MouseEvent e) {
93: adaptee.this_mousePressed(e);
94: }
95:
96: public void mouseReleased(MouseEvent e) {
97: adaptee.this_mouseReleased(e);
98: }
99: }
100:
101: class Lines_this_mouseMotionAdapter
[ccc]extends java.awt.event.MouseMotionAdapter {
102: Lines adaptee;
103:
104: Lines_this_mouseMotionAdapter(Lines adaptee) {
105: this.adaptee = adaptee;
106: }
107:
108: public void mouseDragged(MouseEvent e) {
109: adaptee.this_mouseDragged(e);
110: }
111: }
Modifier testen
case BUTTON1_MASK:
// linke Taste
break;
case BUTTON2_MASK:
// mittlere Taste
break;
case BUTTON3_MASK:
// rechte Taste
break;
}
Tastaturereignisse
int modifiers, int keyCode, char keyChar)
Tastaturereignisse
System.out.println("A keyPressed event occurred.");
System.out.println("Keyboard Key: " + e.getKeyText(e.getKeyCode()));
}
void textArea1_keyReleased(KeyEvent e) {
System.out.println("A keyReleased event occurred.");
System.out.println("Keyboard Key: " + e.getKeyText(e.getKeyCode()));
}
void textArea1_keyTyped(KeyEvent e) {
System.out.println("A keyTyped event occurred.");
System.out.println("Keyboard Key: " + e.getKeyText(e.getKeyCode()));
}
Keyboard Key: A
A keyTyped event occurred.
Keyboard Key: Unknown keyCode: 0x0
A keyReleased event occurred.
Keyboard Key: A
Das Ereignis keyTyped gibt an die Methode getKeyCode() den Wert VK_UNDEFINED zurück, der für
getKeyText() »Unknown keyCode: 0x0« ergibt. Dies passiert, weil das keyTyped-Ereignis einfach
verwendet wird, um zu ermitteln, ob eine alphanumerische Taste gedrückt wurde. Es ist egal, welche
alphanumerische Taste das war, Sie verarbeiten einfach nur das keyTyped-Ereignis, und Sie sind fertig.
Pfeil nach oben + Pfeil nach unten + Eingabetaste
Keyboard Key: Up
A keyReleased event occurred.
Keyboard Key: Up
A keyPressed event occurred.
Keyboard Key: Down
A keyReleased event occurred.
Keyboard Key: Down
A keyPressed event occurred.
Keyboard Key: Enter
A keyTyped event occurred.
Keyboard Key: Unknown keyCode: 0x0
A keyReleased event occurred.
Keyboard Key: Enter
Daran erkennen Sie, daß zwar alle alphanumerischen Taste ein keyTyped-Ereignis auslösen, aber nicht alle
anderen Tastencodes. Die Tasten Pfeil-nach-oben und Pfeil-nach-unten beispielsweise nicht, wohl aber die
Eingabetaste. Seien Sie also vorsichtig im Umgang mit keyTyped für nicht-alphanumerische Tastencodes.
Das Applet KeyTest
int currX;
int currY;
this.setBackground(Color.green);
currY = (getSize().height / 2);
case e.VK_UP:
currY -= 5;
break;
case e.VK_DOWN:
currY += 5;
break;
case e.VK_LEFT:
currX -= 5;
break;
case e.VK_RIGHT:
currX += 5;
break;
default:
currKey = e.getKeyChar();
}
repaint();
g.drawString(String.valueOf(currKey), currX, currY);
}
2: import java.awt.event.*;
3: import java.applet.*;
4: import borland.jbcl.layout.*;
5: import borland.jbcl.control.*;
6:
7: public class KeyTest extends Applet {
8: char currKey = 'A';
9: int currX;
10: int currY;
11: XYLayout xYLayout1 = new XYLayout();
12: boolean isStandalone = false;
13:
14: //Applet erzeugen
15: public KeyTest() {
16: }
17:
18: //Applet initialisieren
19: public void init() {
20: try { jbInit(); } catch (Exception e) { e.printStackTrace(); }
21: currX = (getSize().width / 2);
22: currY = (getSize().height / 2);
23: }
24:
25: // Komponenten initialisieren
26: public void jbInit() throws Exception{
27: this.addKeyListener(new KeyTest_this_keyAdapter(this));
28: this.setFont(new Font("Helvetica", 1, 36));
29: this.setBackground(Color.green);
30: xYLayout1.setWidth(400);
31: xYLayout1.setHeight(300);
32: this.setLayout(xYLayout1);
33: this.requestFocus();
34: }
35:
36: public String getAppletInfo() {
37: return "Applet Information";
38: }
39:
40: // Parameter-Information ermitteln
41: public String[][] getParameterInfo() {
42: return null;
43: }
44:
45: void this_keyPressed(KeyEvent e) {
46: switch (e.getKeyCode()) {
47: case e.VK_UP:
48: currY -= 5;
49: break;
50: case e.VK_DOWN:
51: currY += 5;
52: break;
53: case e.VK_LEFT:
54: currX -= 5;
55: break;
56: case e.VK_RIGHT:
57: currX += 5;
58: break;
59: default:
60: currKey = e.getKeyChar();
61: }
62: repaint();
63: }
64:
65: public void paint(Graphics g) {
66: g.drawString(String.valueOf(currKey), currX, currY);
67: }
68: }
69:
70: class KeyTest_this_keyAdapter extends java.awt.event.KeyAdapter {
71: KeyTest adaptee;
72:
73: KeyTest_this_keyAdapter(KeyTest adaptee) {
74: this.adaptee = adaptee;
75: }
76:
77: public void keyPressed(KeyEvent e) {
78: adaptee.this_keyPressed(e);
79: }
80: }
Standardereignisse
Aktionsereignisse
String command, int modifiers)
if (btnColor.equals("Red"))
this.setBackground(Color.red);
else if (btnColor.equals("Orange"))
this.setBackground(Color.orange);
else if (btnColor.equals("Yellow"))
this.setBackground(Color.yellow);
else if (btnColor.equals("Green"))
this.setBackground(Color.green);
else if (btnColor.equals("Blue"))
this.setBackground(Color.blue);
else if (btnColor.equals("Purple"))
this.setBackground(Color.magenta);
repaint();
2: import java.awt.event.*;
3: import java.applet.*;
4: import borland.jbcl.layout.*;
5: import borland.jbcl.control.*;
6:
7: public class ActionTest extends Applet {
8: boolean isStandalone = false;
9: Button redBtn = new Button();
10: Button orangeBtn = new Button();
11: Button yellowBtn = new Button();
12: Button greenBtn = new Button();
13: Button blueBtn = new Button();
14: Button purpleBtn = new Button();
15: FlowLayout flowLayout1 = new FlowLayout();
16:
17: // Applet erzeugen
18: public ActionTest() {
19: }
20:
21: // Applet initialisieren
22: public void init() {
23: try { jbInit(); } catch (Exception e) { e.printStackTrace(); }
24: }
25:
26: // Initialisierung der Komponenten
27: public void jbInit() throws Exception{
28: this.setBackground(Color.gray);
29: redBtn.setLabel("Red");
30: redBtn.addActionListener(new
[ccc]ActionTest_redBtn_actionAdapter(this));
31: orangeBtn.setLabel("Orange");
32: orangeBtn.addActionListener(new
[ccc]ActionTest_orangeBtn_actionAdapter(this));
33: yellowBtn.setLabel("Yellow");
34: yellowBtn.addActionListener(new
[ccc]ActionTest_yellowBtn_actionAdapter(this));
35: greenBtn.setLabel("Green");
36: greenBtn.addActionListener(new
[ccc]ActionTest_greenBtn_actionAdapter(this));
37: blueBtn.setLabel("Blue");
38: blueBtn.addActionListener(new
[ccc]ActionTest_blueBtn_actionAdapter(this));
39: purpleBtn.setLabel("Purple");
40: purpleBtn.addActionListener(new
[ccc]ActionTest_purpleBtn_actionAdapter(this));
41: this.setLayout(flowLayout1);
42: this.add(redBtn, null);
43: this.add(orangeBtn, null);
44: this.add(yellowBtn, null);
45: this.add(greenBtn, null);
46: this.add(blueBtn, null);
47: this.add(purpleBtn, null);
48: }
49:
50: // Applet-Information ermitteln
51: public String getAppletInfo() {
52: return "Applet Information";
53: }
54:
55: // Parameter-Information ermitteln
56: public String[][] getParameterInfo() {
57: return null;
58: }
59:
60: void colorBtn_actionPerformed(ActionEvent e) {
61: String btnColor = e.getActionCommand();
62: if (btnColor.equals("Red"))
63: this.setBackground(Color.red);
64: else if (btnColor.equals("Orange"))
65: this.setBackground(Color.orange);
66: else if (btnColor.equals("Yellow"))
67: this.setBackground(Color.yellow);
68: else if (btnColor.equals("Green"))
69: this.setBackground(Color.green);
70: else if (btnColor.equals("Blue"))
71: this.setBackground(Color.blue);
72: else if (btnColor.equals("Purple"))
73: this.setBackground(Color.magenta);
74: repaint();
75: }
76: }
77:
78: class ActionTest_redBtn_actionAdapter
[ccc]implements java.awt.event.ActionListener {
79: ActionTest adaptee;
80:
81: ActionTest_redBtn_actionAdapter(ActionTest adaptee) {
82: this.adaptee = adaptee;
83: }
84:
85: public void actionPerformed(ActionEvent e) {
86: adaptee.colorBtn_actionPerformed(e);
87: }
88: }
89:
90: class ActionTest_orangeBtn_actionAdapter
[ccc]implements java.awt.event.ActionListener {
91: ActionTest adaptee;
92:
93: ActionTest_orangeBtn_actionAdapter(ActionTest adaptee) {
94: this.adaptee = adaptee;
95: }
96:
97: public void actionPerformed(ActionEvent e) {
98: adaptee.colorBtn_actionPerformed(e);
99: }
100: }
101:
102: class ActionTest_yellowBtn_actionAdapter
[ccc]implements java.awt.event.ActionListener {
103: ActionTest adaptee;
104:
105: ActionTest_yellowBtn_actionAdapter(ActionTest adaptee) {
106: this.adaptee = adaptee;
107: }
108:
109: public void actionPerformed(ActionEvent e) {
110: adaptee.colorBtn_actionPerformed(e);
111: }
112: }
113:
114: class ActionTest_greenBtn_actionAdapter
[ccc]implements java.awt.event.ActionListener {
115: ActionTest adaptee;
116:
117: ActionTest_greenBtn_actionAdapter(ActionTest adaptee) {
118: this.adaptee = adaptee;
119: }
120:
121: public void actionPerformed(ActionEvent e) {
122: adaptee.colorBtn_actionPerformed(e);
123: }
124: }
125:
126: class ActionTest_blueBtn_actionAdapter
[ccc]implements java.awt.event.ActionListener {
127: ActionTest adaptee;
128:
129: ActionTest_blueBtn_actionAdapter(ActionTest adaptee) {
130: this.adaptee = adaptee;
131: }
132:
133: public void actionPerformed(ActionEvent e) {
134: adaptee.colorBtn_actionPerformed(e);
135: }
136: }
137:
138: class ActionTest_purpleBtn_actionAdapter
[ccc]implements java.awt.event.ActionListener {
139: ActionTest adaptee;
140:
141: ActionTest_purpleBtn_actionAdapter(ActionTest adaptee) {
142: this.adaptee = adaptee;
143: }
144:
145: public void actionPerformed(ActionEvent e) {
146: adaptee.colorBtn_actionPerformed(e);
147: }
148: }
Anpassungsereignisse
int type, int value)
valueSBar.setValue(v);
valueLbl.setText(String.valueOf(v));
2: import java.awt.event.*;
3: import java.applet.*;
4: import borland.jbcl.layout.*;
5: import borland.jbcl.control.*;
6:
7: public class ScrollTest extends Applet {
8: XYLayout xYLayout1 = new XYLayout();
9: boolean isStandalone = false;
10: Label valueLbl = new Label();
11: Scrollbar valueSBar = new Scrollbar();
12:
13: //Get a parameter value
14: public String getParameter(String key, String def) {
15: return isStandalone ? System.getProperty(key, def) :
16: (getParameter(key) != null ? getParameter(key) : def);
17: }
18:
19: // Applet erzeugen
20: public ScrollTest() {
21: }
22:
23: //Initialize the applet
24: public void init() {
25: try { jbInit(); } catch (Exception e) { e.printStackTrace(); }
26: }
27:
28: // Komponenten initialisieren
29: public void jbInit() throws Exception{
30: this.setBackground(Color.cyan);
31: this.setLayout(xYLayout1);
32: this.add(valueLbl, new XYConstraints(21, 21, 54, 30));
33: this.add(valueSBar, new XYConstraints(96, 21, 270, 30));
34: xYLayout1.setWidth(400);
35: xYLayout1.setHeight(300);
36: valueLbl.setFont(new Font("TimesRoman", 1, 24));
37: valueLbl.setAlignment(2);
38: valueLbl.setText("0");
39: valueSBar.setOrientation(0);
40: valueSBar.addAdjustmentListener(new
[ccc]ScrollTest_valueSBar_adjustmentAdapter(this));
41: }
42:
43: // Applet-Information ermitteln
44: public String getAppletInfo() {
45: return "Applet Information";
46: }
47:
48: // Parameter-Information ermitteln
49: public String[][] getParameterInfo() {
50: return null;
51: }
52:
53: void valueSBar_adjustmentValueChanged(AdjustmentEvent e) {
54: int v = e.getValue();
55: valueSBar.setValue(v);
56: valueLbl.setText(String.valueOf(v));
57: }
58: }
59:
60: class ScrollTest_valueSBar_adjustmentAdapter
[ccc]implements java.awt.event.AdjustmentListener {
61: ScrollTest adaptee;
62:
63: ScrollTest_valueSBar_adjustmentAdapter(ScrollTest adaptee) {
64: this.adaptee = adaptee;
65: }
66:
67: public void adjustmentValueChanged(AdjustmentEvent e) {
68: adaptee.valueSBar_adjustmentValueChanged(e);
69: }
70: }
Komponentenereignisse
Fokusereignisse
boolean temporary)
Elementereignisse
Object item, int stateChange)
Fensterereignisse
Zusammenfassung
F&A
Workshop
Quiz
Übungen
© 1997 SAMS
Ein Imprint des Markt&Technik Buch- und Software- Verlag GmbH
Elektronische Fassung des Titels: JBuilder in 14 Tagen, ISBN: 3-87791-895-6