3. La gestion des événements (Event handling).
A chaque fois que l'utilisateur
presse un bouton, appuie sur une touche ou déplace la souris, un
événement est crée par la JVM. Pour qu'un objet puisse
accéder à ces événements, il faut qu'il implémente
une interface lui permettant d'accueillir ce type d'événement.
En effet, il existe une multitude d'événements possible (cf
le tableau ci-contre), et les objets intéressés doivent implémenter
l'interface particulière les intéressant.
Le mécanisme général, est celui de l'abonneur/abonné, c'est-à-dire qu'il existe un abonneur (l'objet qui génére les évenements, event source) et un ou des abonnés (objets qui sont intéressés par ce type d'événement, event listener) qui s'enregistre auprès de cet abonneur. |
|
Comme le montre le tableau, chaque type d'événement est représenté par un objet qui détient les informations concernant l'événement (par exemple, le contenu de la touche ayant été actionné) ainsi que le producteur de l'événement (par exemple, une zone de saisie). Les producteurs d'événements sont généralements des composants atomiques - comme les zones de saisies JTextField, les listes de choix JComboBox, ou les menus JMenu - mais peuvent etre aussi n'importe quel objet non Swing implémentant les mécanismes d'abonnements (i.e. addXXXListener(XXXListener) et removeXXXListener(XXXListener)).
Dans ce mécanisme, chaque abonneur peut avoir plusieurs abonnés, et réciproquement chaque abonné peut s'abonner auprès de plusieurs abonneurs (ne produisant pas forcément le meme type d'événement). Voici un petit schéma permettant de synthétiser tout cela :
Comment implémenter un traitement d'événement (Event handler) :
Pour mettre en place un listener pour un type d'événement donné, trois étapes sont nécessaires :
public class MyClass implements ActionListener { ... } |
someComponent.addActionListener(instanceOfMyClass); |
public void actionPerformed(ActionEvent evt){ // code de traitement de l'événement evt} |
Parfois on utilise des classes internes (voire anonymes) pour effectuer le traitement d'événement dans la classe meme ou à lieu l'abonnement. Cela permet de ne pas éclater et alourdir le code (les classes internes pouvant accéder directement aux attributs de la classe englobante).
Le traitement d'événement et le flux d'exécution :
Le code associé aux événements est exécuté dans un unique thread : le thread de distribution des événements (event-dispatching thread). Cela permet d'assurer que chaque traitement est fini avant de passer au suivant. Cela signifie que tant que l'on est pas sorti de la méthode actionPerformed (dans l'exemple précédant), l'affichage est gelé - et ne se rafraichira pas et ne répondra pas à un autre événement !
Important: Cela entraine que le code de traitement d'événement
doit s'exécuter très rapidement ! Sinon, l'utilisateur décelera
des temps de latence, un manque de réactivité et trouvera
l'interface peu ergonomique ... Si on est dans le cas ou le traitement
d'événement est long, il faut alors créer un nouveau
thread qui se chargera d'effectuer ce traitement en dehors de l'event-dispatching
thread.