Gestió d'esdeveniments
- Processament d'esdeveniments
- Classes anònimes i expressions Lambda
- Mètodes per afegir gestors i filtres
Els esdeveniments notifiquen a l'aplicació de les accions de l'usuari. Els esdeveniments són subclasses d'Event
. Per exemple, MouseEvent
, KeyEvent
, DragEvent
o WindowEvent
.
Partim d'un exemple: un clic del ratolí a un botó. Llavors, un esdeveniment es compon de:
- Destí: el node on succeïx l'esdeveniment. Pot ser una finestra, una escena o un node. En l'exemple, el botó.
- Origen: el lloc on es genera l'esdeveniment. En l'exemple, el ratolí.
- Tipus: el tipus. En l'exemple, clicar el ratolí.
Processament d'esdeveniments
El processament de l'esdeveniment és el següent:
- Selecció del destí:
- Si és un esdeveniment de tecles (keys), l'element que tingui el focus.
- Si és un esdeveniment de mouse, l'element a sota. Si hi ha més d'un, el que estigui a sobre.
- Construcció de l'encaminament: en funció de la jerarquia dels nodes. És el camí des del stage fins arribar al node destí.
- Captura (camí des del stage fins al destí). Aquí no es criden els gestors, però sí els filtres, que poden consumir l'esdeveniment amb
event.consume()
i finalitzar la captura. - Retorn (bombolla): pel camí de tornada cap al stage. Aquí es criden els gestors. Si el gestor d'un node no consumeix l'esdeveniment, un gestor del node pare pot fer-ho, permetent gestors comuns per diversos nodes fill.
Classes anònimes i expressions Lambda
Exemple de gestió d'un esdeveniment d'un botó (control de tipus Button
):
button.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
System.out.println("Botó clicat!");
}
});
Aquest codi utilitza classes anònimes.
També podem utilitzar expressions Lambda, ja que els gestors d'esdeveniments són interfícies funcionals (un sol mètode abstracte):
buttn.setOnAction(
event -> System.out.println("Botó clicat!")
);
Mètodes per afegir gestors i filtres
Els filtres permeten gestionar el processament de l'esdeveniment i consumir-lo, si cal.
<T extends Event> void addEventFilter(
EventType<T> eventType, EventHandler<? super T> eventFilter)
<T extends Event> void removeEventFilter(
EventType<T> eventType, EventHandler<? super T> eventFilter)
Els gestors (handlers) permeten a les aplicacions prendre accions en funció del seu tipus, origen i destí.
<T extends Event> void addEventHandler(
EventType<T> eventType, EventHandler<? super T> eventHandler)
<T extends Event> void removeEventHandler(
EventType<T> eventType, EventHandler<? super T> eventHandler)
Per als gestors tenim els mètodes generals que hem vist i els mètodes de conveniència .setXXX()
que faciliten escriure el codi sense haver d'indicar el tipus d'esdeveniment. Tots els setters treballen amb un sol handler, mentre que l'add/remove permet afegir diversos handlers al mateix esdeveniment.
button.addEventHandler(MouseEvent.MOUSE_CLICKED, mouseHandler);
button.setEventHandler(MouseEvent.MOUSE_CLICKED, mouseHandler);
button.setOnMouseClicked(mouseHandler);
button.setOnAction(actionHandler);
Aquests són alguns dels mètodes de conveniència disponibles:
- General:
setOnAction
- Ratolí:
setOnMouseClicked, setOnMouseEntered, setOnMouseExited, setOnMousePressed
- Teclat:
setOnKeyTyped, setOnKeyPressed, setOnKeyReleased
En general, setOnAction
funciona per tots els controls. Hi ha casos especials, com per exemple si volem atendre el canvi de qualsevol contingut d'un TextField. Es pot utilitzar:
TextField.textProperty().addListener(ChangeListener listener)
I per escoltar un índex numèric sobre un ChoiceBox
:
ChoiceBox.getSelectionModel().selectedIndexProperty().addListener(ChangeListener listener)
Pots veure la llista de controls i com utilitzar-los.