Tit   Inh   Ind   1   2   3   4   5   6   7   8   9   10   11   12   13   14   15   16   17   18   19   20   21   22   23   24   25   26   27   28   29   30   31   32   <<   <   >   >> 

19.6 Key-Events



Unter Windows werden alle Tastatureingaben an die fokussierte Komponente gesendet. Ein Empfänger für Key-Events muß 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)
java.awt.Component

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)
java.awt.event.KeyListener

Um die Funktionsweise dieser Methoden im Zusammenspiel mit den Methoden der Klasse KeyEvent besser verstehen zu können, wollen wir zwischen Zeichentasten und Funktionstasten unterscheiden. Zeichentasten sind dabei solche Tasten, mit denen Buchstaben, Ziffern oder sonstige gültige Unicode-Zeichen eingegeben werden, wie z.B. [a], [A], [B], [1], [2], [%], [+], aber auch [ESC], [LEER] oder [TAB]. Zu den Funktionstasten gehören beispielsweise [F1], [F2], [POS1] oder [CURSORLINKS], aber auch die Umschalttasten [STRG], [ALT] und [UMSCHALT].

 Hinweis 

Die Methode keyTyped wird immer dann aufgerufen, wenn eine Zeichentaste gedrückt wurde. Beim Drücken einer Funktionstaste wird sie dagegen nicht aufgerufen. Im Gegensatz dazu wird keyPressed 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. Die Methode keyReleased wird aufgerufen, wenn eine gedrückte Taste losgelassen wurde, unabhängig davon, ob es sich um eine Zeichen- oder Funktionstaste handelt.

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()
java.awt.event.KeyEvent

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. Tabelle 19.4 gibt eine Übersicht der wichtigsten virtuellen Keycodes der Klasse KeyEvent.

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]

Tabelle 19.4: Virtuelle Key-Codes

Am einfachsten ist es, innerhalb von keyTyped mit getKeyChar die Zeichentasten abzufragen. Dabei liefert getKeyChar stets den ASCII-Code der gedrückten Zeichentaste, Funktionstasten werden nicht übertragen. Der Rückgabewert von getKeyCode ist in diesem Fall immer KeyEvent.VK_UNDEFINED. Sollen dagegen auch Funktionstasten abgefragt werden, muß die Methode keyPressed überlagert werden. Hier ist etwas Vorsicht geboten, denn es wird auf alle Tastendrücke reagiert, und sowohl getKeyCode als auch getKeyChar liefern Werte zurück. Die Unterscheidung von Zeichen- und Funktionstasten kann in diesem Fall mit Hilfe von getKeyChar vorgenommen werden, deren Rückgabewert die Konstante KeyEvent.CHAR_UNDEFINED ist, wenn eine Funktionstaste gedrückt wurde.

Die is-Methoden sind bereits bekannt, mit ihnen können die Umschalttasten abgefragt werden. Das ist beispielsweise 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.

Insgesamt ist das Handling von Tastatur-Events nicht ganz trivial und erfordert ein wenig Aufwand bei der Unterscheidung von Zeichen-, Funktions-, Umschalt- oder Feststelltasten. Tabelle 19.5 faßt die bisherigen Ausführungen noch einmal zusammen. 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.

getKeyCode getKeyChar
keyTyped Zeichentaste: VK_UNDEFINED
Funktionstaste: --
Zeichentaste: Taste als char
Funktionstaste: --
keyPressed Zeichentaste: VK_...
Funktionstaste: VK_...
Zeichentaste: Taste als char
Funktionstaste: CHAR_UNDEFINED

Tabelle 19.5: Rückgabecodes bei Tastaturereignissen

Das folgende Beispiel demonstriert die Abfrage der Tastaturereignisse. Es implementiert keyPressed, um die Funktiontasten [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.

001 /* Listing1906.java */
002 
003 import java.awt.*;
004 import java.awt.event.*;
005 
006 class WindowClosingAdapter
007 extends WindowAdapter
008 {
009   public void windowClosing(WindowEvent event)
010   {
011 	event.getWindow().setVisible(false);
012 	event.getWindow().dispose();
013 	System.exit(0);
014   }
015 }
016 
017 public class Listing1906
018 extends Frame
019 implements KeyListener
020 {
021   String msg1 = "";
022   String msg2 = "";
023 
024   public static void main(String[] args)
025   {
026 	Listing1906 wnd = new Listing1906();
027   }
028 
029   public Listing1906()
030   {
031 	super("Listing1906");
032 	addKeyListener(this);
033 	addWindowListener(new WindowClosingAdapter());
034 	setBackground(Color.lightGray);
035 	setSize(300,200);
036 	setLocation(200,100);
037 	setVisible(true);
038   }
039 
040   public void paint(Graphics g)
041   {
042 	if (msg1.length() > 0) {
043 	  draw3DRect(g,20,50,250,30);
044 	  g.setColor(Color.black);
045 	  g.drawString(msg1,30,70);
046 	}
047 	if (msg2.length() > 0) {
048 	  draw3DRect(g,20,100,250,30);
049 	  g.setColor(Color.black);
050 	  g.drawString(msg2,30,120);
051 	}
052   }
053 
054   void draw3DRect(Graphics g,int x,int y,int width,int height)
055   {
056 	g.setColor(Color.darkGray);
057 	g.drawLine(x,y,x,y+height);
058 	g.drawLine(x,y,x+width,y);
059 	g.setColor(Color.white);
060 	g.drawLine(x+width,y+height,x,y+height);
061 	g.drawLine(x+width,y+height,x+width,y);
062   }
063 
064   public void keyPressed(KeyEvent event)
065   {
066 	msg1 = "";
067 	System.out.println(
068       "key pressed: " + 
069 	  "key char = " + event.getKeyChar() + "  " +
070 	  "key code = " + event.getKeyCode()
071 	);
072 	if (event.getKeyChar() == KeyEvent.CHAR_UNDEFINED) {
073 	  int key = event.getKeyCode();
074 	  //Funktionstaste abfragen
075 	  if (key == KeyEvent.VK_F1) {
076 		msg1 = "F1";
077 	  } else if (key == KeyEvent.VK_F2) {
078 		msg1 = "F2";
079 	  } else if (key == KeyEvent.VK_F3) {
080 		msg1 = "F3";
081 	  }
082 	  //Modifier abfragen
083 	  if (msg1.length() > 0) {
084 		if (event.isAltDown()) {
085 		  msg1 = "ALT + " + msg1;
086 		}
087 		if (event.isControlDown()) {
088 		  msg1 = "STRG + " + msg1;
089 		}
090 		if (event.isShiftDown()) {
091 		  msg1 = "UMSCHALT + " + msg1;
092 		}
093 	  }
094 	}
095 	repaint();
096   }
097 
098   public void keyReleased(KeyEvent event)
099   {
100 	System.out.println("key released");
101 	msg1 = "";
102 	repaint();
103   }
104 
105   public void keyTyped(KeyEvent event)
106   {
107 	char key = event.getKeyChar();
108 	System.out.println("key typed: " + key);
109 	if (key == KeyEvent.VK_BACK_SPACE) {
110 	  if (msg2.length() > 0) {
111 		msg2 = msg2.substring(0,msg2.length() - 1);
112 	  }
113 	} else if (key >= KeyEvent.VK_SPACE) {
114 	  if (msg2.length() < 40) {
115 		msg2 += event.getKeyChar();
116 	  }
117 	}
118 	repaint();
119   }
120 }
Listing1906.java
Listing 19.6: Reaktion auf Tastaturereignisse

 Beispiel 

Eine beispielhafte Ausgabe des Programms ist:

Abbildung 19.5: Darstellung von Tastaturereignissen


 Tit   Inh   Ind   1   2   3   4   5   6   7   8   9   10   11   12   13   14   15   16   17   18   19   20   21   22   23   24   25   26   27   28   29   30   31   32   <<   <   >   >> 
Go To Java 2, Addison Wesley, Version 1.0.2, © 1999 Guido Krüger, http://www.gkrueger.com