Eventos. Capturando las entrada por teclado

En este tutorial veremos como funcionan los eventos y en particular como obtener la información acerca de los eventos producidos en el teclado desde un programa java. Además explicaremos el concepto y uso de clases anónimas que es el método más comúnmente usado para manejar eventos en java. Abandonaremos nuestro juego momentáneamente y haremos un simple ejemplo de captura de eventos.

Ejemplo de lectura del teclado

Para leer del teclado es necesario registrar un objeto que se encargue de "escuchar si una tecla es presionada". Este objeto conocido como "Listener" u "oyente" y tendrá métodos que serán llamados cuando alguien presione una tecla. En nuestro ejemplo el Listener se registra en el JPanel (o KeyboardExample) usando el método addKeyListener(KeyListener listener).

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()));
		}
	}
}

En el constructor de la clase KeyboardExample creamos el listener y lo registramos. Para que un objeto JPanel reciba las notificaciones del teclado es necesario incluir la instrucción setFocusable(true) que permite que KeyboardExample reciba el foco.

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

La clase MyKeyListener es la que uso para crear el objeto Listener. Este Listener imprimirá en la consola el nombre del método y la tecla afectada por el evento.

	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()));
		}
	}

Una vez registrado, cuando KeyboardExample (nuestro JPanel) tenga el foco y alguien oprima una tecla KeyboardExample informará al objeto listener registrado. El objeto Listener de nuestro ejemplo implementa la interfaz KeyListener que tiene los métodos keyTyped(), keyPressed() y keyReleased(). El método keyPressed será llamado cada vez que una tecla sea oprimida (y varias veces si se mantiene oprimida). El método keyReleased será llamado cuando solemos una tecla.

Los métodos antes mencionados reciben como parámetro un objeto KeyEvent que contiene información sobre que tecla se ha oprimido o soltado. Usando e.getKeyCode() podemos obtener el código de la tecla y si le pasamos un código de tecla a la función estatica KeyEvent.getKeyText(...) podemos obtener el texto asociado a la tecla.

¿Cómo funcionan los eventos en AWT/Swing?

Lo eventos del ratón y el teclado son controlados por el sistema operativo. El motor AWT, en particular el thread AWT-Windows se comunica con el sistema operativo y se entera de si hubo un evento. Cuando encuentra un nuevo evento lo coloca en la "Cola de Eventos" para que sea atendido cuando le llegue su turno por el Thread AWT-EventQueue.

Cuando el Thread AWT-EventQueue atiende a un evento se fija a que componente afecta y le informa. En nuestro caso el componente es el JPanel que informa a todos los listeners que se hayan registrado para recibir notificaciones de ese evento.

En el caso del teclado la llamada addKeyListener(KeyListener listener) es la que realiza este registro. Si queremos registrar un objeto para escuchar los eventos del ratón podemos usar addMouseListener(MouseListener listener).

Si quieren profundizar en como funcionan los eventos en AWT/Swing les recomiendo el siguiente artículo.

Clase anónima

En el ejemplo anterior la clase MyKeyListener será solo usada una vez por lo que podríamos reemplazarla por una clase anónima. KeyboardExample2 muestra como sería:

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);
	}
}

En el constructor de la clase KeyboardExample2 podemos ver como se reemplaza

       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()));
			}
		};

Esta instrucción tiene el mismo efecto que la anterior. Reemplaza la definición de la clase MyKeyListener por una clase anónima que hace exactamente lo mismo.

La forma de crear un objeto desde una clase anónima es reemplazar el nombre de la clase a crear por una definición que empieza por la interfaz a implementar seguida por () y luego dentro de {} la definición de la clase como hacemos normalmente.

Aunque parezca un poco extraño esta es la forma más cómoda de implementar Listeners de eventos y es la forma que más encontrarán en código java avanzado.

Ahora sigamos con el desarrollo de nuestro juego en el próximo tutorial.

 

<< Anterior Siguiente >>