1. Introducción a los eventos
En programación, un evento es una señal de que algo ha ocurrido. Puede ser una pulsación de botón, la introducción de texto, la finalización de la carga de datos, el cambio del valor de una variable — cualquier cosa que pueda suceder en tu aplicación y a la que, como desarrollador, quieras reaccionar.
Si hacemos una analogía, un evento es como el timbre de la puerta: alguien ha llegado y tú decides qué hacer a continuación. Puedes abrir la puerta, ignorarlo, hacer como si no estuvieras en casa o incluso llamar a toda la familia para ver quién es. En programación, el evento es «el timbre» y tu reacción es el manejador del evento.
En Java los eventos son la base de la programación reactiva y de interfaces gráficas (GUI). Sin ellos no existirían los botones, las listas desplegables, las aplicaciones de ventana e incluso muchos sistemas de servidor.
Escuchador (Listener): qué es y para qué sirve
Un escuchador (Listener) es un objeto que se suscribe a un evento concreto y espera a que ocurra. En cuanto sucede, el escuchador recibe la señal y ejecuta el código de reacción indicado.
En Java, los escuchadores suelen implementarse mediante interfaces. Uno de los ejemplos más comunes es la interfaz ActionListener. La implementan clases que deben reaccionar a acciones del usuario, por ejemplo, la pulsación de un botón.
En la práctica, la interacción se organiza así: hay una fuente del evento, por ejemplo un botón, y hay un escuchador — un objeto que implementa la interfaz necesaria. La fuente mantiene una lista de todos los escuchadores que se han suscrito a ella. Cuando el usuario pulsa el botón, la fuente del evento invoca un método especial en cada uno de los escuchadores.
Este esquema se parece a una suscripción de noticias: mientras estés suscrito, recibirás notificaciones. En el caso de Java, esa notificación es la llamada a un método del escuchador, que realiza acciones descritas de antemano.
2. Interfaces de eventos: ActionListener, MouseListener y otros
En Java, para cada tipo de evento existe una interfaz de escuchador específica:
| Tipo de evento | Interfaz de escuchador | Dónde se utiliza |
|---|---|---|
| Acción | |
Botones, menús, temporizadores |
| Ratón | |
Componentes que reaccionan al ratón |
| Teclado | |
Campos de texto, cualquier componente |
| Cambio | |
Deslizadores, casillas de verificación, modelos de datos |
| Documento | |
Cambios en el texto (por ejemplo, JTextField) |
Cada una de estas interfaces define uno o varios métodos que hay que implementar. Por ejemplo, ActionListener requiere implementar el método actionPerformed(ActionEvent e).
Ejemplo: ActionListener
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
class MyActionListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("¡Se pulsó el botón!");
}
}
3. Principio de funcionamiento del modelo de eventos
Todo el modelo de eventos de Java se basa en un mecanismo simple pero potente:
- La fuente del evento (por ejemplo, un botón) mantiene una lista de escuchadores.
- Cuando ocurre alguna acción (por ejemplo, el usuario hace clic en el botón), la fuente crea un objeto de evento (por ejemplo, ActionEvent).
- La fuente recorre todos los escuchadores registrados y llama en ellos al método correspondiente (por ejemplo, actionPerformed), pasando el objeto del evento.
- Cada escuchador decide por sí mismo qué hacer con ese evento.
Esquema del funcionamiento de los eventos:
flowchart LR
A[El usuario pulsó el botón] --> B[El botón creó el evento]
B --> C[El botón invoca actionPerformed en todos los escuchadores]
C --> D[El escuchador reacciona: ejecuta su código]
Ejemplo de código:
import javax.swing.*;
public class EventDemo {
public static void main(String[] args) {
JButton button = new JButton("¡Púlsame!");
button.addActionListener(new MyActionListener());
JFrame frame = new JFrame("Ejemplo de evento");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(button);
frame.setSize(200, 100);
frame.setVisible(true);
}
}
Cuando el usuario pulsa el botón, se ejecuta el método actionPerformed de todos los escuchadores.
4. Ejemplo: añadir un escuchador a un botón
Veamos el esquema clásico con un ejemplo sencillo.
Paso 1. Creamos el botón
JButton button = new JButton("Decir hola");
Paso 2. Creamos el escuchador
class HelloListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("¡Hola, mundo!");
}
}
Paso 3. Registramos el escuchador
button.addActionListener(new HelloListener());
En breve: así se ve en el código
JButton button = new JButton("Decir hola");
button.addActionListener(new HelloListener());
5. Clases anónimas y expresiones lambda: breve y práctico
Clase anónima
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Escuchador anónimo: ¡hola!");
}
});
Expresión lambda (Java 8+)
button.addActionListener(e -> System.out.println("¡Lambda! ¡Hola!"));
Una lambda es la forma más concisa de añadir un escuchador cuando tu reacción al evento son una o dos líneas.
6. ¿Cómo se relaciona esto con tu aplicación?
Integramos este mecanismo en tu aplicación de aprendizaje. Por ejemplo, tenemos una ventana sencilla con el botón «Añadir tarea». Al pulsar el botón, queremos añadir una nueva tarea a la lista y mostrar un mensaje.
Ejemplo de código:
import javax.swing.*;
import java.awt.event.ActionListener;
public class TaskManagerGUI {
public static void main(String[] args) {
JFrame frame = new JFrame("Gestor de tareas");
JButton addButton = new JButton("Añadir tarea");
// Usamos una lambda como escuchador
addButton.addActionListener(e -> {
System.out.println("¡Tarea añadida!");
// Aquí podría ir la lógica de añadir la tarea a la lista
});
frame.add(addButton);
frame.setSize(300, 100);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
¡Ahora tu aplicación no solo ejecuta instrucciones, sino que «reacciona» a las acciones del usuario!
7. Errores típicos al trabajar con escuchadores y eventos
Error n.º 1: olvidaste registrar el escuchador. Si creaste un escuchador pero no lo añadiste a la fuente del evento, tu código nunca se ejecutará. Es como suscribirte a una revista sin enviar la solicitud: la revista no llegará.
Error n.º 2: registraste el mismo escuchador varias veces. Si añades accidentalmente el mismo escuchador varias veces, el manejador se llamará tantas veces como lo añadiste. A veces es útil, pero la mayoría de las veces es el origen de errores extraños («¿por qué mi función se ejecuta tres veces?»).
Error n.º 3: olvidaste eliminar el escuchador. Si el escuchador ya no es necesario pero no lo eliminas, seguirá colgado en memoria. En aplicaciones de larga vida esto puede provocar fugas de memoria.
Error n.º 4: operaciones pesadas en el manejador del evento. Si haces un trabajo pesado directamente en el manejador (por ejemplo, cargar datos de Internet), la interfaz «se queda congelada» y el usuario se pone nervioso. Es mejor ejecutar el trabajo pesado en un hilo separado.
Error n.º 5: excepciones no controladas en el escuchador. Si en tu manejador se produce una excepción, puede «romper» toda la cadena de eventos. Registra los errores y controla las excepciones para que la aplicación no se caiga.
GO TO FULL VERSION