In the sections that follow, we will discuss in more detail the events that are not linked to specific user interface components, in particular, events related to keystrokes and mouse activity. You can find a detailed discussion of semantic events generated by user interface components in the next chapter.

Keyboard Events

When the user pushes a key, a key_Pressed KeyEvent is generated. When the user releases the key, a key_Release KeyEvent is triggered. You trap these events in the keyPressed and keyReleased methods of any class that implements the KeyListener interface. Use these methods to trap raw keystrokes. A third method, keyTyped, combines the two: it reports on the characters that were generated by the user's keystrokes. The best way to see what happens is with an example. But before we can do that, we have to add a little more terminology. Java makes a distinction between characters and virtual key codes. Virtual key codes are indicated with a prefix of VK_, such as VK_A or VK_SHIFT. Virtual key codes correspond to keys on the keyboard. For example, VK_A denotes the key marked A. There is no separate lowercase virtual key code-the keyboard does not have separate lowercase keys.Java graphics notes_icon

Virtual key codes are similar (and related to) the scan codes of a PC keyboard.So, suppose that the user types an uppercase "A" in the usual way, by pressing the SHIFT key along with the A key. Java reports five events in response to this user action. Here are the actions and the associated events:

  1. Pressed the SHIFT key (keyPressed called for VK_SHIFT)
  2. Pressed the A key (keyPressed called for VK_A)
  3. Typed "A" (keyTyped called for an "A")
  4. Released the A key (keyReleased called for VK_A)
  5. Released the SHIFT key (keyReleased called for VK_SHIFT)

On the other hand, if the user typed a lowercase "a" by simply pressing the A key, then there are only three events:

  1. Pressed the A key (keyPressed called for VK_A)
  2. Typed "a" (keyTyped called for an "a")
  3. Released the A key (keyReleased called for VK_A)

Thus, the keyTyped procedure reports the character that was typed ("A" or "a"), whereas the keyPressed and keyReleased methods report on the actual keys that the user pressed. To work with the keyPressed and keyReleased methods, you want to first check the key code.

public void keyPressed(KeyEvent event)
{
 int keyCode = event.getKeyCode();
 . . .
}

The key code will equal one of the following (reasonably mnemonic) constants. They are defined in the KeyEvent class.

VK_A . . . VK_Z VK_0 . . . VK_9
VK_COMMA, VK_PERIOD, VK_SLASH, VK_SEMICOLON, VK_EQUALS VK_OPEN_BRACKET, VK_BACK_SLASH, VK_CLOSE_BRACKET VK_BACK_QUOTE, VK_QUOTE VK_GREATER, VK_LESS, VK_UNDERSCORE, VK_MINUS VK_AMPERSAND, VK_ASTERISK, VK_AT, VK_BRACELEFT, VK_BRACERIGHT VK_LEFT_PARENTHESIS, VK_RIGHT_PARENTHESIS VK_CIRCUMFLEX, VK_COLON, VK_NUMBER_SIGN, VK_QUOTEDBL VK_EXCLAMATION_MARK, VK_INVERTED_EXCLAMATION_MARK VK_DEAD_ABOVEDOT, VK_DEAD_ABOVERING, VK_DEAD_ACUTE VK_DEAD_BREVE VK_DEAD_CARON, VK_DEAD_CEDILLA, VK_DEAD_CIRCUMFLEX VK_DEAD_DIAERESIS VK_DEAD_DOUBLEACUTE, VK_DEAD_GRAVE, VK_DEAD_IOTA, VK_DEAD_MACRON VK_DEAD_OGONEK, VK_DEAD_SEMIVOICED_SOUND, VK_DEAD_TILDE VK_DEAD_VOICED_SOUND VK_DOLLAR, VK_EURO_SIGN VK_SPACE, VK_ENTER, VK_BACK_SPACE, VK_TAB, VK_ESCAPE VK_SHIFT, VK_CONTROL, VK_ALT, VK_ALT_GRAPH, VK_META VK_NUM_LOCK, VK_SCROLL_LOCK, VK_CAPS_LOCK VK_PAUSE, VK_PRINTSCREEN VK_PAGE_UP, VK_PAGE_DOWN, VK_END, VK_HOME, VK_LEFT, VK_UP VK_RIGHT VK_DOWN VK_F1 . . .VK_F24
VK_NUMPAD0 . . . VK_NUMPAD9
VK_KP_DOWN, VK_KP_LEFT, VK_KP_RIGHT, VK_KP_UP VK_MULTIPLY, VK_ADD, VK_SEPARATER [sic], VK_SUBTRACT, VK_DECIMAL VK_DIVIDE VK_DELETE, VK_INSERT VK_HELP, VK_CANCEL, VK_CLEAR, VK_FINAL VK_CONVERT, VK_NONCONVERT, VK_ACCEPT, VK_MODECHANGE VK_AGAIN, VK_ALPHANUMERIC, VK_CODE_INPUT, VK_COMPOSE, VK_PROPS VK_STOP VK_ALL_CANDIDATES, VK_PREVIOUS_CANDIDATE VK_COPY, VK_CUT, VK_PASTE, VK_UNDO VK_FULL_WIDTH, VK_HALF_WIDTH VK_HIRAGANA, VK_KATAKANA, VK_ROMAN_CHARACTERS VK_KANA, VK_KANJI VK_JAPANESE_HIRAGANA, VK_JAPANESE_KATAKANA, VK_JAPANESE_ROMAN VK_UNDEFINED

To find the current state of the SHIFT, CONTROL, ALT, and META keys, you can, of course, track the VK_SHIFT, VK_CONTROL, VK_ALT, and VK_META key presses, but that is tedious. Instead, simply use the isShiftDown, isControlDown, isAltDown, and isMetaDown methods. For example, the following code tests whether the user presses SHIFT + RIGHT ARROW:

public void keyPressed(KeyEvent event)
{
 int keyCode = event.getKeyCode();
 if (keyCode == KeyEvent.VK_RIGHT && event.isShiftDown())
 {
 . . .
 }
}

In the keyTyped method, you call the getKeyChar method to obtain the actual character that was typed.Java graphics notes_icon

Not all keystrokes result in a call to keyTyped. Only those keystrokes that generate a Unicode character can be captured in the keyTyped method. You need to use the keyPressed method to check for cursor keys and other command keys. shows how to handle keystrokes. The program (shown in ) is a simple implementation of the Etch-A-Sketch toy.

A sketch program

Java graphics 08fig07

You move a pen up, down, left, and right with the cursor keys. If you hold down the SHIFT key, the pen moves by a larger increment. Or, if you are experienced using the vi editor, you can bypass the cursor keys and use the lowercase h, j, k, and l keys to move the pen. The uppercase H, J, K, and L move the pen by a larger increment. We trap the cursor keys in the keyPressed method and the characters in the keyTyped method. There is one technicality: Normally, a panel does not receive any key events. To override this default, we call the setFocusable method. We discuss the concept of keyboard focus later in this chapter.

Example Sketch.java

 1. import java.awt.*;
 2. import java.awt.geom.*;
 3. import java.util.*;
 4. import java.awt.event.*;
 5. import javax.swing.*;
 6.
 7. public class Sketch
 8. {
 9. public static void main(String[] args)
 10. {
 11. SketchFrame frame = new SketchFrame();
 12. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 13. frame.show();
 14. }
 15. }
 16.
 17. /**
 18. A frame with a panel for sketching a figure
 19. */
 20. class SketchFrame extends JFrame
 21. {
 22. public SketchFrame()
 23. {
 24. setTitle("Sketch");
 25. setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
 26.
 27. // add panel to frame
 28.
 29. SketchPanel panel = new SketchPanel();
 30. Container contentPane = getContentPane();
 31. contentPane.add(panel);
 32. }
 33.
 34. public static final int DEFAULT_WIDTH = 300;
 35. public static final int DEFAULT_HEIGHT = 200;
 36. }
 37.
 38. /**
 39. A panel for sketching with the keyboard.
 40. */
 41. class SketchPanel extends JPanel
 42. {
 43. public SketchPanel()
 44. {
 45. last = new Point2D.Double(100, 100);
 46. lines = new ArrayList();
 47. KeyHandler listener = new KeyHandler();
 48. addKeyListener(listener);
 49. setFocusable(true);
 50. }
 51.
 52. /**
 53. Add a new line segment to the sketch.
 54. @param dx the movement in x direction
 55. @param dy the movement in y direction
 56. */
 57. public void add(int dx, int dy)
 58. {
 59. // compute new end point
 60. Point2D end = new Point2D.Double(last.getX() + dx,
 61. last.getY() + dy);
 62.
 63. // add line segment
 64. Line2D line = new Line2D.Double(last, end);
 65. lines.add(line);
 66. repaint();
 67.
 68. // remember new end point
 69. last = end;
 70. }
 71.
 72. public void paintComponent(Graphics g)
 73. {
 74. super.paintComponent(g);
 75. Graphics2D g2 = (Graphics2D)g;
 76.
 77. // draw all lines
 78. for (int i = 0; i < lines.size(); i++)
 79. g2.draw((Line2D)lines.get(i));
 80. }
 81.
 82. private Point2D last;
 83. private ArrayList lines;
 84.
 85. private static final int SMALL_INCREMENT = 1;
 86. private static final int LARGE_INCREMENT = 5;
 87.
 88. private class KeyHandler implements KeyListener
 89. {
 90. public void keyPressed(KeyEvent event)
 91. {
 92. int keyCode = event.getKeyCode();
 93.
 94. // set distance
 95. int d;
 96. if (event.isShiftDown())
 97. d = LARGE_INCREMENT;
 98. else
 99. d = SMALL_INCREMENT;
100.
101. // add line segment
102. if (keyCode == KeyEvent.VK_LEFT) add(-d, 0);
103. else if (keyCode == KeyEvent.VK_RIGHT) add(d, 0);
104. else if (keyCode == KeyEvent.VK_UP) add(0, -d);
105. else if (keyCode == KeyEvent.VK_DOWN) add(0, d);
106. }
107.
108. public void keyReleased(KeyEvent event) {}
109.
110. public void keyTyped(KeyEvent event)
111. {
112. char keyChar = event.getKeyChar();
113.
114. // set distance
115. int d;
116. if (Character.isUpperCase(keyChar))
117. {
118. d = LARGE_INCREMENT;
119. keyChar = Character.toLowerCase(keyChar);
120. }
121. else
122. d = SMALL_INCREMENT;
123.
124. // add line segment
125. if (keyChar == 'h') add(-d, 0);
126. else if (keyChar == 'l') add(d, 0);
127. else if (keyChar == 'k') add(0, -d);
128. else if (keyChar == 'j') add(0, d);
129. }
130. }
131.}

java.awt.event.KeyEvent 1.1

Java graphics api_icon