Eventos y acción de los componentes
Cómo JavaFX detecta que "ha pasado algo" (un clic, una tecla, un movimiento de ratón), cómo viaja ese aviso por el grafo de escena y cómo reaccionar a él.
1Qué es un evento
Un evento es una señal que indica que ha ocurrido algo: un clic, la pulsación de una tecla, un cambio de texto, el movimiento del ratón, la finalización de una tarea, etc.
- Evento (Event): el tipo de evento que ocurre.
- Fuente de evento (Event source): el origen del evento (p.ej. un botón).
- Destino de evento (Event target): el nodo al que se dirige el evento.
- Manejador de evento (Event handler): el objeto oyente que implementa
EventHandlercon su métodohandle().
| Categoría | Clase base | Ejemplo |
|---|---|---|
| Acción | ActionEvent | Pulsar botón, seleccionar menú |
| Ratón | MouseEvent | Clic, movimiento, arrastre |
| Teclado | KeyEvent | Pulsar o soltar tecla |
| Desplazamiento | ScrollEvent | Desplazamiento con la rueda |
| Entrada de texto | InputMethodEvent | Escribir texto |
| Foco | FocusEvent | Ganar/perder el foco |
| Arrastrar/soltar | DragEvent | Drag and drop |
| Ventana | WindowEvent | Mostrar/ocultar ventanas |
| Personalizados | Event | Definidos por el programador |
2Propagación del evento (cuatro fases)
- Selección del objetivo: JavaFX decide qué nodo recibe el evento (teclado → nodo con foco; ratón → nodo bajo el cursor; si hay nodos superpuestos, el superior/visible lo recibe).
- Construcción de la ruta: se arma una cadena de envío (event dispatch chain) desde el nodo raíz (Stage) hasta el nodo objetivo. Ejemplo:
Stage → Scene → Pane → Rectangle → Triangle (objetivo). - Captura del evento: el evento viaja desde la raíz hacia el objetivo; en cada paso se ejecutan los Event Filters que existan. Si uno consume el evento (
event.consume()), no llega al objetivo. - Burbujeo del evento: el evento regresa desde el objetivo hacia el Stage, ejecutando los Event Handlers. Si un manejador lo consume, los nodos superiores no lo procesan.
| Mecanismo | Cuándo actúa | Efecto de consumir |
|---|---|---|
| Event Filter | Antes de llegar al objetivo (fase de captura) | El evento no llega al hijo |
| Event Handler | Después de llegar al objetivo (fase de burbujeo) | El evento no sube al padre |
event.consume(); // detiene la propagación del evento
3Tres formas de manejar un evento
// 1) Clase anónima
Button btn = new Button("Haz clic");
btn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent e) {
System.out.println("¡Has hecho clic en el botón!");
}
});
// 2) Expresión lambda
Button btn2 = new Button("Haz clic");
btn2.setOnAction(e -> System.out.println("¡Botón presionado!"));
// 3) Implementando EventHandler en una clase
public class MiManejador implements EventHandler<ActionEvent> {
@Override
public void handle(ActionEvent e) {
System.out.println("Evento manejado desde otra clase.");
}
}
btn.setOnAction(new MiManejador());
Añadir un manejador siempre sigue tres pasos: (1) tener una fuente de evento (un control que puede generar eventos), (2) crear el manejador implementando EventHandler y su método handle(), (3) registrarlo con un método como setOnAction().
public class HolaMundo extends Application {
@Override
public void start(Stage primaryStage) {
Button btn = new Button();
btn.setText("Escribir 'Hola mundo'");
btn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
System.out.println("¡Hola mundo!");
}
});
StackPane root = new StackPane();
root.getChildren().add(btn);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hola mundo.");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
4Ejemplos: ratón, teclado y burbujeo
button.setOnMouseEntered(e -> System.out.println("El ratón está sobre el botón"));
button.setOnMouseExited(e -> System.out.println("El ratón salió del botón"));
button.setOnMousePressed(e -> System.out.println("Botón del ratón presionado"));
button.setOnMouseReleased(e -> System.out.println("Botón del ratón soltado"));
button.setOnMouseClicked(e -> System.out.println("Clic completo"));
e.getButton(); // Botón del ratón (PRIMARY, SECONDARY...)
e.getX(); // Coordenada X del clic
e.getY(); // Coordenada Y del clic
scene.setOnKeyPressed(e -> System.out.println("Tecla presionada: " + e.getCode()));
scene.setOnKeyReleased(e -> System.out.println("Tecla liberada: " + e.getCode()));
e.getCode(); // Devuelve el código de la tecla (KeyCode.A, KeyCode.ENTER, etc.)
Ejemplo de burbujeo: un clic sobre un círculo dentro de un VBox dispara primero el manejador del círculo y después el del VBox (a menos que el primero consuma el evento).
circle.addEventHandler(MouseEvent.MOUSE_CLICKED, e -> {
System.out.println("Círculo clicado. Fuente: "
+ e.getSource().getClass().getSimpleName());
// e.consume(); // Descomentar para evitar el burbujeo
});
root.addEventHandler(MouseEvent.MOUSE_CLICKED, e -> {
System.out.println("VBox clicado. Fuente: "
+ e.getSource().getClass().getSimpleName());
System.out.println("Target del evento: "
+ e.getTarget().getClass().getSimpleName());
});
Ejemplo completo combinando estilo dinámico en hover y una alerta al pulsar:
Button btn = new Button("Haz clic aquí");
btn.setStyle("-fx-font-size: 14px; -fx-padding: 10px 20px; "
+ "-fx-background-color: lightgray;");
btn.setOnMouseEntered(e -> {
btn.setStyle("-fx-font-size: 14px; -fx-padding: 10px 20px; "
+ "-fx-background-color: lightgray; "
+ "-fx-border-color: blue; -fx-border-width: 2px; "
+ "-fx-border-insets: 2px;");
});
btn.setOnMouseExited(e -> {
btn.setStyle("-fx-font-size: 14px; -fx-padding: 10px 20px; "
+ "-fx-background-color: lightgray;");
});
btn.setOnAction(e -> {
Alert alerta = new Alert(AlertType.INFORMATION);
alerta.setTitle("Mensaje");
alerta.setHeaderText(null);
alerta.setContentText("Bienvenido a JavaFX");
alerta.showAndWait();
});
✓Ideas clave que debes dominar
- Cuatro fases: selección del objetivo → construcción de la ruta → captura (filtros) → burbujeo (handlers).
event.consume()corta la propagación en el punto donde se llama.- Tres formas de manejar un evento: clase anónima, lambda, clase que implementa
EventHandler.
Adaptado de Eventos y acción de los componentes.