INTRODUCTION |
Jusqu’à présent, on a abordé uniquement des programmes ne comportant qu’un seul fil d’événements, les instructions étant exécutées les unes après les autres dans l’ordre du programme avec des boucles et des conditions. Ainsi, le fil d’exécution du programme est complètement déterminé par les paramètres initiaux. Ce modèle ne convient pas bien au pilotage d’un programme avec une souris car on ne peut pas savoir où en est l’exécution du programme lors d’un clic de souris. Pour pouvoir capturer les clics de souris, il faut introduire un nouveau concept de programmation appelé contrôle par les événements ou programmation événementielle. Le principe en est le suivant : Il faut définir une fonction portant un nom quelconque, par exemple onMouseHit() qui n’est jamais appelée explicitement par le programme. Ensuite, on demander à l’ordinateur d’appeler cette fonction à chaque fois qu’il détecte un clic de souris. En résumé, on demande au programme d’exécuter la fonction onMouseHit() à chaque fois que l’utilisateur clique sur le bouton de la souris. |
ÉVÉNEMENTS DE LA SOURIS |
Il est très facile d’implémenter ce nouveau concept en Python. Dans notre premier programme dirigé par les événements, la tortue doit dans un premier temps dessiner une figure sympathique. Ensuite, l’utilisateur peut décorer ce dessin initial en cliquant avec la souris sur certaines zones pour les colorier. Le programme ci-dessous définit la fonction onMouseHit(x, y), qui sera appelée par le système en lui fournissant en guise de paramètres les coordonnées de la souris lors de clic. On peut ensuite utiliser ces coordonnées pour colorier la figure fermée qui entoure le point (x, y) à l’aide de la fonction fill(x, y).
from gturtle import * def onMouseHit(x, y): fill(x, y) makeTurtle(mouseHit = onMouseHit) hideTurtle() addStatusBar(30) setStatusText("Click to fill a region!") repeat 12: repeat 6: forward(80) right(60) left(30)
|
MEMENTO |
Du point de vue technique, la programmation événementielle est implémentée en définissant une fonction appelée gestionnaire d’événements (event handler en anglais) qui sera appelée sans que l’on s’en occupe à chaque fois que le système d’exploitation détecte un certain type d’événement. Pour que cela fonctionne, il faut informer le système de notre gestionnaire d’événement en passant le nom de la fonction (sans parenthèse !!!) au paramètre approprié de la fonction makeTurtle(). Pour cela, on utilise la notion très utile en Python de paramètre nommé avec la notation parameter_name = parameter_value. On peut régler les préférences pour la couleur de remplissage avec la fonction setFillColor().La fonction addStatusBar(n) permet d’afficher des informations utiles pour l’utilisateur dans une barre d’état en-dessous de la fenêtre de la tortue. Le nombre entier b permet de spécifier la hauteur de ligne du texte affiché dans la barre d’état. |
DESSINER AVEC UN ÉVÉNEMENT DE LA SOURIS |
from gturtle import * def onMouseHit(x, y): setPos(x, y) repeat 6: dot(40) forward(60) back(60) right(60) makeTurtle(mouseHit = onMouseHit) speed(-1) |
MEMENTO |
Ce programme est bogué : si l’utilisateur clique une seconde fois avant que l’étoile précédente ne soit terminée, l’étoile en cours ne va pas être terminée et le programme commence directement le dessin de la seconde étoile. De plus, les instructions non exécutées de l’étoile précédente vont être exécutées dans la deuxième étoile, ce qui mènera à un dessin incorrect de la deuxième étoile. Ce comportement erroné est apparemment dû au fait qu’à chaque clic de la souris, la fonction onMouseHit() est appelée et exécutée, même si l’exécution précédente n’est pas encore terminée. Pour prévenir ce problème, il faut passer la fonction onMouseHit au paramètre mouseHitX au lieu de mouseHit lors de l’appel de makeTurtle(). |
CHASSE À LA SOURIS |
from gturtle import * def onMouseMoved(x, y): setHeading(towards(x, y)) forward(10) makeTurtle(mouseMoved = onMouseMoved) speed(-1) |
MEMENTO |
En plus de mouseHit et mouseHitX, la fonction makeTurtle() met d’autres paramètres à disposition permettant de détecter des événements de la souris. Ces événements, au lieu de prendre les coordonnées x et y comme paramètres, prennent un seul paramètre event à l’aide duquel on peut déterminer les coordonnées de la souris lors de l’événement ainsi que d’autres informations.
Il est également possible d’enregistrer plusieurs gestionnaires d’événements différents en spécifiant simultanément plusieurs paramètres, par exemple les deux fonctions onMousePressed() et onMouseDragged : makeTurtle(mousePressed = onMousePressed, mouseDragged = onMouseDragged)On peut déterminer lequel des boutons a été cliqué grâce aux fonctions isLeftMouseButton() et isRightMouseButton(). Les événements listés ci-dessus comportent une différence importance avec mouseHit : le mouvement de la tortue n’est pas visible pendant l’exécution de la fonction. De ce fait, il faut soit régler la vitesse de la tortue sur ultrarapide avec speed(-1) et cacher la tortue avec hideTurtle() ou alors exécuter le code du mouvement dans la partie principale du programme. |
from gturtle import * def onMousePressed(x, y): moveTo(x, y) makeTurtle(mousePressed = onMousePressed) #speed(-1) #hideTurtle() |
ÉVÉNEMENTS DU CLAVIER |
À chaque fois qu’une touche du clavier est actionnée, un événement est généré. Pour gérer ce dernier, on enregistre un gestionnaire d’événements en renseignant le paramètre keyPressed. lors de l’appel de la fonction makeTurtle.
from gturtle import * LEFT = 37 RIGHT = 39 UP = 38 DOWN = 40 def onKeyPressed(key): if key == LEFT: setHeading(-90) elif key == RIGHT: setHeading(90) elif key == UP: setHeading(0) elif key == DOWN: setHeading(180) makeTurtle(keyPressed = onKeyPressed) wrap() while True: forward(10) |
EXERCICES |
|
BONUS |
CURSEUR PERSONNALISÉ |
Pourquoi ne pas décorer le programme montré précédemment avec l’image cuteturtle ou votre propre image. Il faut s’assurer que la tortue se déplace toujours vers la souris en utilisant moveTo(). from gturtle import * def onMouseMoved(x, y): moveTo(x, y) makeTurtle(mouseMoved = onMouseMoved) setCustomCursor("sprites/cutemouse.gif") speed(-1) |
MEMENTO |
L’appel speed(-1) évite d’utiliser les animations de la tortue, ce qui rend les dessins avec moveTo() bien plus rapides. Paramètres possible pour la fonction setCursor():
Le dossier sprites utilisé pour spécifier à la fonction setCustomCursor() le chemin vers le curseur doit se trouver dans le même dossier que le programme Python. |