Handling User Events

When a user event is generated by a component that has a listener, a method will be called automatically. The method must be found in the class that was specified when the listener was attached to the component. For instance, in the example of the fireTorpedos object, the method must be located in the same program because the this statement was used. Each listener has different methods that are called to receive their events. The ActionListener interface sends events to a class called actionPerformed(). The following is a short example of an actionPerformed() method:

public void actionPerformed(ActionEvent evt) {
 // method goes here

All action events sent in the program will go to this method. If only one component in a program can possibly send action events, you can put statements in this method to handle the event. If more than one component can send these events, you need to use the object that is sent to the method. In this case, an ActionEvent object is sent to the actionPerformed() method. There are several different classes of objects that represent the user events that can be sent in a program. These classes have methods you can use to determine which component caused the event to happen. In the actionPerformed() method, if the ActionEvent object is named evt, you can identify the component with the following statement:

String cmd = evt.getActionCommand();

The getActionCommand() method sends back a string. If the component is a button, the string will be the label that is on the button. If it's a text field, the string will be the text entered in the field. The getSource() method sends back the object that caused the event. You could use the following actionPerformed() method to receive events from three components: a JButton object called start, a JTextField called speed, and another JTextField called viscosity:

public void actionPerformed(ActionEvent evt) {
 Object source = evt.getSource();
 if (source == speed) {
 // speed field caused event
 } else if (source == viscosity) {
 // viscosity caused event
 } else {
 // start caused event

You can use the getSource() method with all types of user events to identify the specific object that caused the event.

Check Box and Combo Box Events

Combo boxes and check boxes require the ItemListener interface. Call the component's addItemListener() method to make it generate these events. For example, the following statements create a check box called superSize and cause it to send out user events when selected or deselected:

JCheckBox superSize = new JCheckBox("Super Size", true);

These events are received by the itemStateChanged() method, which takes an ItemEvent object as an argument. To see which object caused the event, you can use the getItem() method. To determine whether a check box is selected or deselected, use the getStateChange() method with the constants ItemEvent.SELECTED and ItemEvent.DESELECTED. The following is an example for an ItemEvent object called item:

int status = item.getStateChange();
if (status == ItemEvent.SELECTED) {
 // item was selected

To determine the value that has been selected in a JComboBox object, use getItem() and convert that value to a string, as in the following:

Object which = item.getItem();
String answer = which.toString();

Keyboard Events

One thing that's common in a game program is for the program to react immediately when a key is pressed. Several game programmers, such as Karl Hörnell, have created arcade-style Java applets on web pages that you control through the keyboard using the arrow keys, numeric keypad, spacebar, and other keys. Keyboard events of this kind are handled through the KeyListener interface. The first step is to register the component that receives presses of the keyboard by calling its addKeyListener() method. The argument of the method should be the object that implements the KeyListener interface—if it is the current class, you can use this as the argument. An object that handles keyboard events must implement three methods:

  • void keyPressed(KeyEvent)— This method is called the moment a key is pressed.
  • void keyReleased(KeyEvent)— This method is called the moment a key is released.
  • void keyTyped(KeyEvent)— This method is called after a key has been pressed and released.

Each of these has a KeyEvent object as an argument, and you can call this object's methods to find out more about the event. Call the getKeyChar() method to find out which key was pressed. This key is returned as a char value, and it only can be used with letters, numbers, and punctuation. To monitor any key on the keyboard, including Enter, Home, Page Up, and Page Down, you can call getKeyCode() instead. This method returns an integer value representing the key. You can then call getKeyText() with that integer as an argument to receive a String object containing the name of the key (such as Home, F1, and so on). Listing 15.1 contains a Java app that draws the most recently pressed key in a label by using the getKeyChar() method. The app implements the KeyListener interface, so there are keyTyped(), keyPressed(), and keyReleased() methods in the class. The only one of these that does anything is keyTyped() in Lines 21–24.

Listing 15.1. The Full Text of KeyView.java
 1: import javax.swing.*;
 2: import java.awt.event.*;
 3: import java.awt.*;
 4: 5: public class KeyView extends JFrame implements KeyListener {
 6: JTextField keyText = new JTextField(80);
 7: JLabel keyLabel = new JLabel("Press any key in the text field.");
 8: 9: KeyView() {
10: super("KeyView");
11: setSize(350, 100);
12: setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
13: keyText.addKeyListener(this);
14: BorderLayout bord = new BorderLayout();
15: setLayout(bord);
16: add(keyLabel, BorderLayout.NORTH);
17: add(keyText, BorderLayout.CENTER);
18: setVisible(true);
19: }
20: 21: public void keyTyped(KeyEvent input) {
22: char key = input.getKeyChar();
23: keyLabel.setText("You pressed " + key);
24: }
25: 26: public void keyPressed(KeyEvent txt) {
27: // do nothing
28: }
29: 30: public void keyReleased(KeyEvent txt) {
31: // do nothing
32: }
33: 34: public static void main(String[] arguments) {
35: KeyView frame = new KeyView();
36: }
37: }

When you run the app, it should resemble Screenshot.

Screenshot Handling keyboard events in a program.

Java ScreenShot

By the way

To play Karl Hörnell's Java applets, visit his website at http://www.javaonthebrain.com. He publishes the source code to more than a dozen programs he has written, and provides some explanatory notes for people trying to develop their own games.

Enabling and Disabling Components

You may have seen a component in a program that appears shaded instead of its normal appearance.

By the way

If you haven't seen a shaded component yet, you must have skipped Hour 14, "Laying Out a User Interface." I'm sorry to hear that. Sams Teach Yourself Programming with Java in 23 Hours doesn't have the same ring to it.

Shading indicates that users cannot do anything to the component because it is disabled. Disabling and enabling components as a program runs is done with the setEnabled() method of the component. A Boolean value is sent as an argument to the method, so setEnabled(true) enables a component for use, and setEnabled(false) disables a component. The following statement creates three buttons with the labels Previous, Next, and Finish, and disables the first button:

JButton previousButton = new JButton("Previous");
JButton nextButton = new JButton("Next");
JButton finishButton = new JButton("Finish");

This method is an effective way to prevent a component from sending a user event when it shouldn't. For example, if you're writing a Java app that takes a user's address in text fields, you might want to disable a Save button until all of the fields have some kind of value.