Principes généraux

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 DragEventKeyEventMouseEventScrollEvent, 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 :

  1. La sélection de la cible (Target) de l'événement :
  2. La détermination de la chaîne de traitement des événements (Event Dispatch Chain : chemin des événements dans le graphe de scène). Le chemin part de la racine (Stage) et va jusqu'au composant cible en parcourant tous les nœuds intermédiaires
  3. Le traitement des filtres d'événement (Event Filter) : Exécute le code des filtres en suivant le chemin descendant, de la racine (Stage) jusqu'au composant cible.
  4. Le traitement des gestionnaires d'événement (Event Handler) : Exécute le code des gestionnaires d'événement en suivant le chemin montant, du composant cible à la racine (Stage).

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).

https://cours-info.iut-bm.univ-fcomte.fr/upload/supports/S2/IHM/cours/evenements/capturing.png

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).

https://cours-info.iut-bm.univ-fcomte.fr/upload/supports/S2/IHM/cours/evenements/bubbling.png

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)