Events. Keyboard input

In this tutorial we will see how the events work and particularly how to obtain, from a java program, the information about keyboard events. We will also explain the concept and the use of the anonymous classes, which are the most common way of managing events in java. We will leave aside the game for a moment and we will explain the capture of events in a simple example.

Keyboard reading example

To read from the keyboard it is necessary to register an object which be in charge of "listening if a key is pressed". This object is known as "Listener" and it will have methods that will be called when someone presses a key. In our example the Listener is registered in the JPanel (or KeyboardExample) using the addKeyListener(KeyListener listener) method.

package com.edu4java.minitennis4;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class KeyboardExample extends JPanel {
	
	public KeyboardExample() {
		KeyListener listener = new MyKeyListener();
		addKeyListener(listener);
		setFocusable(true);
	}
	
	public static void main(String[] args) {
		JFrame frame = new JFrame("Mini Tennis");
		KeyboardExample keyboardExample = new KeyboardExample();
		frame.add(keyboardExample);
		frame.setSize(200, 200);
		frame.setVisible(true);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}

	public class MyKeyListener implements KeyListener {
		@Override
		public void keyTyped(KeyEvent e) {
		}

		@Override
		public void keyPressed(KeyEvent e) {
			System.out.println("keyPressed="+KeyEvent.getKeyText(e.getKeyCode()));
		}

		@Override
		public void keyReleased(KeyEvent e) {
			System.out.println("keyReleased="+KeyEvent.getKeyText(e.getKeyCode()));
		}
	}
}

In the constructor of the KeyboardExample class, we create the listener and we register it. So that the JPanel object receives the keyboard notifications it is necessary to include the instruction setFocusable(true), which allows KeyboardExample to receive the focus.

	public KeyboardExample() {
		KeyListener listener = new MyKeyListener();
		addKeyListener(listener);
		setFocusable(true);
	}

The MyKeyListener class is the one I use to create the Listener object. This Listener will write on the console, the name of the method and the key which are affected by the event.

	public class MyKeyListener implements KeyListener {
		@Override
		public void keyTyped(KeyEvent e) {
		}

		@Override
		public void keyPressed(KeyEvent e) {
			System.out.println("keyPressed="+KeyEvent.getKeyText(e.getKeyCode()));
		}

		@Override
		public void keyReleased(KeyEvent e) {
			System.out.println("keyReleased="+KeyEvent.getKeyText(e.getKeyCode()));
		}
	}

Once it is registered, when KeyboardExample (our JPanel) has the focus and someone presses a key, KeyboardExample will report it to the listener registered. The Listener of our example implements the KeyListener interface which has the keyTyped(), keyPressed() and keyReleased() methods. The keyPressed method will be called each time the key is pressed (and several times if the key is maintained pressed).

The keyTyped(), keyPressed() and keyReleased() methods receive a KeyEvent object as a parameter, which contains information on which key has been pressed or released. Using e.getKeyCode() we can obtain the key and if we pass a key code to KeyEvent.getKeyText(...), we can obtain the text which is associated to the key.

How does the events work in AWT/Swing?

The keyboard and mouse events are controled by the operative system. The AWT engine and in particular the AWT-Windows thread comunicate with the operative system and knows when an event occurs. When a new event comes along it is placed in the "Event queue" so that it is attended by the AWT-EventQueue thread in its turn.

When the AWT-EventQueue thread attends an event, it pays attention at what component it affects and it informs him. In our case the component is the JPanel, which informs all the listeners which are registered to receive notifications for this event.

In the case of the keyboard, the call to addKeyListener(KeyListener listener) is the one which carries out this register. If we want to register an object to listen to the events of the mouse we can use addMouseListener(MouseListener listener).

If you want more information on how do the events work in AWT/Swing, I recommend you the following article.

Anonymous Class

In the previous example the MyKeyListener class will be only used once, so we could replace it with an anonymous class. KeyboardExample2 shows how would it be:

package com.edu4java.minitennis4;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class KeyboardExample2 extends JPanel {
	
	public KeyboardExample2() {
		KeyListener listener = new KeyListener() {
			@Override
			public void keyTyped(KeyEvent e) {
			}

			@Override
			public void keyPressed(KeyEvent e) {
				System.out.println("keyPressed="+KeyEvent.getKeyText(e.getKeyCode()));
			}

			@Override
			public void keyReleased(KeyEvent e) {
				System.out.println("keyReleased="+KeyEvent.getKeyText(e.getKeyCode()));
			}
		};
		addKeyListener(listener);
		setFocusable(true);
	}
	
	public static void main(String[] args) {
		JFrame frame = new JFrame("Mini Tennis");
		KeyboardExample2 keyboardExample = new KeyboardExample2();
		frame.add(keyboardExample);
		frame.setSize(200, 200);
		frame.setVisible(true);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
}

In the constructor of the KeyboardExample2 class we can se how to replace it

       KeyListener listener = new MyKeyListener();

por

		KeyListener listener = new KeyListener() {
			@Override
			public void keyTyped(KeyEvent e) {
			}

			@Override
			public void keyPressed(KeyEvent e) {
				System.out.println("keyPressed="+KeyEvent.getKeyText(e.getKeyCode()));
			}

			@Override
			public void keyReleased(KeyEvent e) {
				System.out.println("keyReleased="+KeyEvent.getKeyText(e.getKeyCode()));
			}
		};

This instruction has the same effect as the previous one. It replaces the definition of the MyKeyListener class for an anonymous class which does exactly the same thing.

The way to create an object from an anonymous class is to replace the name of the class we want to create with a definition which starts with the interface we want to implement, followed with a (), and inside {}, the definition of the class as we do always.

Even if it looks a bit strange, this is the best way of implementing the events Listeners and it is the way you will see it in most of advanced java code.

In the next tutorial we will continue to develop our game.

 

<< Sprites - Speed and direction Adding the sprite "racquet" >>