La programmation des applications avec interfaces graphiques est généralement basée sur la programmation événementielle. Ce sont les événements (généralement déclenchés par l'utilisateur, mais aussi par le système) qui pilotent l'application. Donc, la programmation événementielle nécessite qu'un processus (en tâche de fond) surveille constamment les actions de l'utilisateur susceptibles de déclencher des événements qui pourront être ensuite traités (ou non) par l'application.
En effet, après la création de l'interface graphique, il faut associer du code à chaque événement que l'on souhaite traiter (Register Callback). Lorsque l'utilisateur interagit avec l'interface graphique, des évènements sont générés et le code associé à chacun de ces évènements est automatiquement exécuté par le processus de surveillance qui tourne en tâche de fond.
Tous les objets graphiques de JavaFX sont capables de générer des évènements. Par exemple, lorsque l'utilisateur clique sur un bouton, un évènement de type ActionEvent
est généré par le bouton. Les évènements notifient l'application des actions entreprises par l'utilisateur et permettent à l'application de réagir à cet évènement. La plateforme JavaFx permet de capturer un évènement généré afin de le traiter.
<aside> ☝ Un évènement représente la survenance de quelque chose dans l'application comme l'activation d'un bouton.
</aside>
En JavaFX, l'évènement est une instance de la classe javafx.event.Event
ou d'une sous-classe de cette dernière. Il est possible de définir un nouvel évènement en créant une sous classe d'Event
et il y a des évènements prédéfinis comme DragEvent
, KeyEvent
, MouseEvent
, ScrollEvent
, etc.
Un évènement comprend plusieurs informations comme le type de l'évènement (consultable avec getEventType()
), la source (consultable avec getSource()
), etc. Un type d'événement peut avoir un sous-type, par exemple : L'évènement KeyEvent
contient les sous-types suivants : KEY_PRESSED
, KEY_RELEASED
et KEY_TYPED
.
Le traitement des événements implique les étapes suivantes :
Exemple :
Si un utilisateur appuie sur le bouton Insert, un événement de type ActionEvent
va être déclenché et va se propager d'abord vers le bas, depuis le nœud racine (Stage) jusqu'à la cible (Target), le long du chemin correspondant à la chaîne de traitement (Event Dispatch Chain). Les filtres (Event Filter) pour l'évènement ActionEvent
, éventuellement enregistrés sur les noeuds du chemin, sont exécutés (dans l'ordre de passage).
L'événement remonte ensuite depuis la cible jusqu'à la racine (en suivant le même chemin mais dans l'autre sens) et les gestionnaires d'événements (Event Listener) pour l’événement ActionEvent
, éventuellement enregistrés sur les nœuds du chemin, sont exécutés (dans l'ordre de passage).
Chaque récepteur d'événement (filtre ou gestionnaire) peut interrompre la chaîne de traitement en consommant l'événement, c’est-à-dire en invoquant la méthode consume()
. Par suite, la propagation de l'événement s'interrompt et les autres récepteurs (qui suivent dans la chaîne de traitement) ne seront plus activés.
Pour gérer un événement d'un type donné, il faut créer un écouteur d'événement qui capte ce type d'évènement, et l'enregistrer sur les nœuds du graphe de scène où l'on souhaite intercepter l'événement et effectuer un traitement. Un écouteur d'événement peut être enregistré comme filtre ou comme gestionnaire d'événement. La différence principale entre les deux réside dans le moment où le code est exécuté : Les filtres (filters) sont exécutés dans la phase descendante de la chaîne de traitement des événements (avant les gestionnaires) et les gestionnaires (handlers) sont exécutés dans la phase montante de la chaîne de traitement des événements (après les filtres). Les filtres, comme les gestionnaires d'événements, sont des objets qui doivent implémenter l'interface EventHandler
qui impose la définition de l'unique méthode handle()
qui se charge de traiter l'événement.
public void handle(event-class eventName)