Einführung in JAVA Low-Level-Events 1
Übersicht: - Window-Events - Component-Events - Mouse-Events - MouseMotion-Events - Focus-Events - Key-Events Inhaltverzeichnis 2
Übersicht 3
Übersicht 4
Window-Events: - Bedeutung - Übersicht der Methoden von WindowsListener - Beispiel Window-Events 5
Window-Event wird immer dann generiert, wenn sich am Status eines Fensters eine Änderung ergeben hat Statusänderungen: - neues Fenster erstellen - Fenster zerstören - Aktivieren/ Deaktivieren - Symbolisieren - Wiederherstellung Empfänger für Window-Events muss das Interface WindowListener implementieren und bekommt Events des Typs WindowEvent übergeben. Methode getwindow: zur Ermittlung des Fensters, welches die Nachricht ausgelöst hat. public Window getwindow() Die Registrierung der Empfängerklasse erfolgt mit der Methode addwindowlistener, die in den Klassen Dialog und Frame zur Verfügung steht: public void addwindowlistener(windowlistener l) Window-Events/ Bedeutung 6
Ereignismethode Bedeutung windowactivated Das Fenster wurde aktiviert. Aufruf beim: erstellen des Fensters vom Hintergrund in den Vordergrund windowclosed Das Fenster wurde geschlossen. windowclosing Das Fenster soll geschlossen werden. Aufruf: Wenn der Anwender das Fenster über die Titelleiste, das Systemmenü oder die Tastenkombination [ALT]+[F4] schließen will. Window-Events/ Übersicht der Methoden 7
Ereignismethode Bedeutung windowdeactivated windowdeiconified windowiconified windowopened Das Fenster wurde deaktiviert, also in den Hintergrund gestellt. Das Fenster wurde wiederhergestellt, nachdem es zuvor auf Symbolgröße verkleinert worden war. Das Fenster wurde auf Symbolgröße verkleinert. Das Fenster wurde geöffnet. Window-Events/ Übersicht der Methoden 8
public class Listing2901 { public static void main(string[] args) { CloseableFrame wnd = new CloseableFrame("CloseableFrame"); wnd.setbackground(color.lightgray); wnd.setsize(300,200); wnd.setlocation(200,100); wnd.setvisible(true); wnd.addwindowlistener( new WindowAdapter() { public void windowclosed(windowevent event) { System.out.println("terminating program..."); System.exit(0); } } ); } } Beispiel/ Programmauszug 9
Component-Events: - Bedeutung - Übersicht der Methoden von ComponentListener - Beispiel Component-Events 10
Component-Event wird generiert, wenn: - eine Komponente verschoben - ihre Größe verändert wurde - wenn sich der Anzeigezustand einer Komponente verändert Da sowohl Fenster als auch alle Dialogelemente aus der Klasse Component abgeleitet sind, haben die hier erwähnten Ereignisse für nahezu alle GUI-Elemente (Graphical User Interface) des AWT (Abstract Windowing Toolkit ) Gültigkeit. Ein Empfänger für Component-Events muss das Interface ComponentListener implementieren und bekommt Events des Typs ComponentEvent übergeben. Component-Events/ Bedeutung 11
ComponentEvent erweitert die Klasse AWTEvent und stellt neben getid und getsource die Methode getcomponent zur Verfügung, mit der die Komponente ermittelt werden kann, die die Nachricht ausgelöst hat. public Component getcomponent() Die Registrierung der Empfängerklasse erfolgt mit der Methode addcomponentlistener, die in allen aus Component abgeleiteten Klassen zur Verfügung steht: public void addcomponentlistener(componentlistener l) Component-Events/ Bedeutung 12
Ereignismethode Bedeutung componentshown componenthidden componentmoved componentresized Eine Komponente wurde sichtbar. Eine Komponente wurde unsichtbar. Eine Komponente wurde verschoben. Die Größe einer Komponente hat sich geändert. Component-Events / Übersicht der Methoden 13
class ComponentRepaintAdapter extends ComponentAdapter { public void componentmoved(componentevent event) { event.getcomponent().repaint(); } public void componentresized(componentevent event) { event.getcomponent().repaint(); } } Beispiel/ Programmauszug 14
Mouse-Events: - Bedeutung - Übersicht der Methoden von MouseListener - Beispiel Mouse-Events 15
Mouse-Event entsteht, wenn der Anwender innerhalb der Client-Area des Fensters eine der Maustasten drückt oder losläßt. Unterscheidung von: einfachen und doppelten Mausklicks Ein Empfänger für Mouse-Events muss das Interface MouseListener implementieren und bekommt Events des Typs MouseEvent übergeben. MouseEvent erweitert die Klasse InputEvent und stellt neben getid und getsource eine Reihe zusätzlicher Methoden zur Verfügung, die wichtige Informationen liefern. Die Registrierung der Empfängerklasse erfolgt mit der Methode addmouselistener public void addmouselistener(mouselistener l) Mouse-Events / Bedeutung 16
Ereignismethode mousepressed mousereleased mouseclicked mouseentered mouseexited Bedeutung Eine Maustaste wurde gedrückt. Die gedrückte Maustaste wurde losgelassen. Eine Maustaste wurde gedrückt und wieder losgelassen. Diese Methode wird nach mousereleased aufgerufen. Der Mauszeiger wurde in den Client- Bereich der auslösenden Komponente hineinbewegt. Der Mauszeiger wurde aus dem Client- Bereich der auslösenden Komponente herausbewegt. Mouse-Events / Übersicht der Methoden 17
Damit ein Programm auf Mausklicks angemessen reagieren kann, benötigt es zusätzliche Informationen, die es sich mit den Methoden der Klasse MouseEvent beschaffen kann. Mit getx, gety und getposition kann die Position des Mauszeigers zum Zeitpunkt des Ereignisses ermittelt werden: public int getx() public int gety() public Point getpoint() getx liefert die x- und gety die y-koordinate des Punktes, an dem der Mauszeiger sich beim Auftreten des Ereignisses befindet. getpoint liefert dieselbe Information zusammengefasst als Point-Objekt. Mouse-Events 18
Die Koordinatenwerte werden relativ zum Ursprung der auslösenden Komponente angegeben. Bei einem Fenster des Typs Frame bedeutet dies, dass bei einem Klick in der oberen linken Ecke nicht (0,0) zurückgegeben wird, sondern (getinsets().left, getinsets().top). Dies stimmt mit dem Ursprung des Koordinatensystems überein, das auch beim Aufruf der Grafikroutinen zugrunde gelegt wird. Mouse-Events 19
Die Methode getclickcount liefert die Anzahl der Mausklicks, die dem aktuellen Ereignis zugeordnet ist: public int getclickcount() Normalerweise hat dieser Zähler den Wert 1, bei Mehrfachklicks gibt es aber auch MouseEvents mit dem Wert 2 oder (je nach Schnelligkeit der Klicks) noch höheren Werten. Die Abfrage von getclickcount kann dazu verwendet werden, auf Doppelklicks zu reagieren. Hierzu ist lediglich beim Aufruf von mousepressed oder mouseclicked zu überprüfen, ob getclickcount den Wert 2 liefert. In diesem Fall handelt es sich um einen Doppelklick. Mouse-Events / Einfach/Doppelklicks 20
Alternative Methode zur Erkennung eines Doppelklicks: Zeitspanne zwischen zwei Klicks und den Abstand der beiden Koordinatenpaare voneinander zu messen und bei hinreichend kleinen Differenzen einen Doppelklick anstelle zweier Einfachklicks zu melden. Dazu wird mit der Methode getwhen der Klasse InputEvent der Zeitpunkt (in Millisekunden) und mit getpoint oder getx und gety die Mausposition zweier aufeinanderfolgender Events bestimmt: public long getwhen() Vorteil: zeitliche und positionelle Toleranz für Doppelklicks selbst beeinflussbar Mouse-Events / Einfach/Doppelklicks 21
Beim Drücken der linken Maustaste lächelt das Gesicht, bei der rechten sieht es grimmig aus. Bei einem Doppelklick bekommt der Smiley zusätzlich eine Brille aufgesetzt. Die Ausgabe des Programms sieht beispielsweise so aus: Erwähnenswert ist die Tatsache, dass das Programm ohne paint-methode auskommt. Tatsächlich beschafft die Methode mousepressed sich die zum Zeichnen erforderliche Instanz der Klasse Graphics durch Aufruf von getgraphics selbst. Die Methode getgraphics gibt immer den Grafikkontext des aktuellen Fensterobjekts zurück. Beispiel 22
MouseMotion-Events: - Bedeutung - Übersicht der Methoden - Beispiel MouseMotion-Events 23
- klare Trennung zwischen Mouse-Events und MouseMotion-Events - Mouse-Events für Mausklicks und Betreten oder Verlassen der Komponente - MouseMotion-Events Auskunft über die Bewegung des Mauszeigers. Neben der verbesserten Modularisierung wurde die Trennung vor allem deshalb vorgenommen, um Performance-Verbesserungen zu erzielen. Ein Empfänger für MouseMotion-Events muss das Interface MouseMotionListener implementieren. Er wird mit der Methode addmousemotionlistener registriert. public void addmousemotionlistener(mousemotionlistener l) Bedeutung 24
Das Interface MouseMotionListener definiert die Methoden mousemoved und mousedragged: public abstract void mousemoved(mouseevent e) public abstract void mousedragged(mouseevent e) mousemoved wird aufgerufen, wenn die Maus bewegt wird, ohne dass dabei eine der Maustasten gedrückt ist. mousedragged wird dagegen aufgerufen, wenn die Maus bei gedrückter linker oder rechter Maustaste bewegt wird. Bedeutung 25
Zusammenspiel zwischen paint und den Methoden, die die Maus-Events behandeln. Beim Aufruf von paint werden zunächst alle Rechtecke gezeichnet, die sich in der Liste drawlist befinden. Anschließend überprüft paint, ob das aktuelle Element eine Länge oder Breite größer Null hat, und zeichnet es gegebenenfalls. Dies ist genau dann der Fall, wenn der Anwender die Maustaste gedrückt und die Maus vom Ursprung nach rechts unten bewegt hat. Beim Loslassen der Maustaste wird das aktuelle Element in die Liste der Rechtecke eingetragen und steht so beim nächsten paint zur Verfügung Beispiel 26
Focus-Events - Bedeutung - Beispiel Focus-Events 27
Der Fokus zeigt an, welches Fenster die Tastatureingaben erhält. Sind mehrere Fenster gleichzeitig geöffnet, so kann immer nur eines von ihnen den Fokus beanspruchen. Sind auf einem aktiven Fenster mehrere Dialogelemente aktiv, so kann ebenfalls nur eines davon den Fokus erhalten. Ein Empfänger für Focus-Events muss das Interface FocusListener implementieren und bekommt Events des Typs FocusEvent übergeben. FocusEvent erweitert die Klasse ComponentEvent und stellt neben getid und getsource die Methode istemporary zur Verfügung, die anzeigt, ob der Fokuswechsel temporär oder permanent ist: public boolean istemporary() Focus-Events / Bedeutung 28
Die Registrierung von Focus-Events erfolgt mit der Methode addfocuslistener, die auf allen Objekten des Typs Component oder daraus abgeleiteten Objekten zur Verfügung steht: public void addfocuslistener(focuslistener l) Das Interface FocusListener enthält lediglich zwei unterschiedliche Methoden: public abstract void focusgained(focusevent e) Fokus erhalten public abstract void focuslost(focusevent e) Fokus abgegeben Es gibt die Möglichkeit, den Fokus programmgesteuert zu verändern. Dazu gibt es die Methode requestfocus der Klasse Component, mit der eine Komponente den Fokus für sich selbst beanspruchen bzw. ihn einer anderen Komponente zuweisen kann: public void requestfocus() Focus-Events / Bedeutung 29
Das Programm zeigt die Anwendung eines FocusListener-Interfaces zur Implementierung der Methoden focusgained und focuslost auf einem Frame-Objekt. Wenn das Fenster den Eingabefokus erhält, wird der Hintergrund BLAU und gibt die Meldung»Fokus erhalten«aus. Verliert das Fenster den Fokus, so wird der Hintergrund Grau und die Meldung»Kein Fokus«wird angezeigt. Die Registrierung des Fokusempfänger-Objekts erfolgt durch Aufruf von addfocuslistener(this), bei dem das Fensterobjekt sich selbst als Empfänger registriert: public void focusgained(focusevent event) { havefocus = true; setbackground(color.blue); repaint(); } public void focuslost(focusevent event) { havefocus = false; setbackground(color.lightgray); repaint(); } Beispiel 30
Key-Events - Bedeutung - Übersicht der Symbolischen Namen - Beispiel Key-Events 31
Alle Tastatureingaben werden an die fokussierte Komponente gesendet. Ein Empfänger für Key-Events muss das Interface KeyListener implementieren und bekommt Events des Typs KeyEvent übergeben. KeyEvent erweitert die Klasse InputEvent, die ihrerseits aus ComponentEvent abgeleitet ist, und stellt neben getid und getsource eine ganze Reihe von Methoden zur Verfügung, mit denen die Erkennung und Bearbeitung der Tastencodes vereinfacht wird. Die Registrierung von Key-Events erfolgt mit der Methode addkeylistener, die auf allen Objekten des Typs Component oder daraus abgeleiteten Klassen zur Verfügung steht: public void addkeylistener(keylistener l) Bedeutung 32
Das Interface KeyListener definiert drei unterschiedliche Methoden: public abstract void keypressed(keyevent e) public abstract void keyreleased(keyevent e) public abstract void keytyped(keyevent e) Zeichentasten: Buchstaben, Ziffern oder sonstige gültige Unicode-Zeichen z.b. [a], [A], [B], [1], [2], [%], [+], [ESC], [LEER] oder [TAB] Funktionstasten: [F1], [F2], [POS1] oder [CURSORLINKS], Umschalttasten [STRG], [ALT] und [UMSCHALT] Bedeutung 33
keytyped keypressed wird aufgerufen, wenn eine Zeichentaste gedrückt wurde.!!beim Drücken einer Funktionstaste wird sie dagegen nicht aufgerufen. wird bei jedem Tastendruck aufgerufen, unabhängig davon, ob es sich um eine Zeichentaste oder eine Funktionstaste handelt. Mit keypressed können sogar in beschränktem Umfang die Feststelltasten wie [NUMLOCK] oder [CAPSLOCK] erkannt werden. Beide Methoden erhalten auch Tastatur-Repeats, werden also bei längerem Festhalten einer Taste wiederholt aufgerufen. keyreleased wird aufgerufen, wenn eine gedrückte Taste losgelassen wurde unabhängig, ob es sich um eine Zeichen- oder Funktionstaste handelt. Bedeutung 34
Um beim Auftreten eines Tastatur-Events zu erkennen, welche Taste gedrückt wurde, stellt die Klasse KeyEvent die Methoden getkeycode und getkeychar und zusätzlich die aus InputEvent geerbten Methoden isshiftdown, iscontroldown, ismetadown und isaltdown zur Verfügung: public int getkeycode() public char getkeychar() public boolean isshiftdown() public boolean iscontroldown() public boolean ismetadown() public boolean isaltdown() getkeychar liefert das Zeichen, das der gedrückten Zeichentaste entspricht, also ein 'a', wenn die Taste [A] gedrückt wurde, und ein 'A', wenn die Tastenkombination [UMSCHALT]+[A] gedrückt wurde. getkeycode liefert dagegen virtuelle Tastencodes, die in KeyEvent als symbolische Konstanten definiert wurden. Hier wird beim Drücken der Taste [A] immer der Code VK_A geliefert, unabhängig davon, ob [UMSCHALT] gedrückt wurde oder nicht. Bedeutung 35
Symbolischer Name Bedeutung VK_0... VK_9 [0]... [9] VK_A... VK_Z [A]... [Z] VK_ENTER [ENTER] VK_SPACE [LEER] VK_TAB [TAB] VK_ESCAPE [ESC] VK_BACK_SPACE [RÜCK] VK_F1... VK_F12 Die Funktionstasten [F1]... [F12] VK_HOME, VK_END [HOME], [END] VK_INSERT, VK_DELETE [EINFG], [ENTF] VK_PAGE_UP, VK_PAGE_DOWN [BILDHOCH], [BILDRUNTER] VK_DOWN, VK_UP [CURSORHOCH], [CURSORRUNTER] VK_LEFT, VK_RIGHT [CURSORLINKS], [CURSORRECHTS] Key Events / Symbolische Namen 36
Einfachste Abfrage von Zeichentasten mit: getkeychar getkeychar liefert stets den ASCII-Code der gedrückten Zeichentaste Sollen auch Funktionstasten abgefragt werden, muss die Methode keypressed überlagert werden. Mit der is-methoden können die Umschalttasten abgefragt werden. Das ist sinnvoll, um bei einer Funktionstaste herauszufinden, ob sie mit gedrückter Umschalttaste ausgelöst wurde oder nicht. Allerdings sind die Umschalttasten im Event-Modell des JDK 1.1 keine Tottasten, sondern liefern selbst ein Key-Event und lösen die Methode keypressed aus. 37
getkeycode getkeychar keytyped Zeichentaste: VK_UNDEFINED Zeichentaste: Taste als char Funktionstaste: -- Funktionstaste: -- keypressed Zeichentaste: VK_... Zeichentaste: Taste als char Funktionstaste: VK_... Funktionstaste: CHAR_UNDEFINED Die erste Zeile zeigt das Verhalten beim Aufruf der Listener-Methode keytyped an, die zweite beim Aufruf von keypressed. Die erste Spalte liefert dazu den Rückgabewert von getkeycode, die zweite den von getkeychar. Jedes Element beschreibt in der oberen Hälfte den Rückgabewert beim Drücken einer Zeichentaste und in der unteren den beim Drücken einer Funktionstaste. 38
Das folgende Beispiel demonstriert die Abfrage der Tastaturereignisse. Es implementiert keypressed, um die Funktionstasten [F1] bis [F3] und den Status der Umschalttasten abzufragen. Jeder Tastendruck wird in einen String übersetzt, in msg1 gespeichert und durch Aufruf von repaint auf dem Bildschirm angezeigt. Nach dem Loslassen der Taste wird die Anzeige wieder vom Bildschirm entfernt. Weiterhin wurde keytyped überlagert, um die Zeichentasten abzufragen. Jeder Tastendruck wird in msg2 gespeichert und ebenfalls auf dem Bildschirm angezeigt. Im Gegensatz zu den Funktionstasten bleibt die Ausgabe auch erhalten, wenn die Taste losgelassen wird. Bei jedem weiteren Tastendruck wird sie um ein Zeichen ergänzt. Zusätzlich werden die einzelnen Ereignisse auf der Konsole dokumentiert. Beispiel 39
Quelle: Ende 40
Ende 41