Un événement est la survenue de quelquechose dans votre application - par exemple, l’utilisateur appuie sur une touche, clique avec sa souris ou la déplace. Votre application à certainement besoin de réagir à ces actions de l’utilisateur.
Les widgets ont normalement un grand nombre de comportements prédéfinis. Par exemple, un bouton réagira à un clic souris en appelant la fonction associée à son option command. Un autre exemple, si vous déplacez le focus sur un widget de saisie et que vous appuyez sur une lettre, cette lettre sera ajoutée au contenu du widget.
Cependant, tkinter fourni tous les moyens pour ajouter, changer ou supprimer de tels comportements.
Premièrement, quelques définitions:
Vous pouvez lier un gestionnaire à un événement à l’un de ces niveaux:
Liaison au niveau d’un widget: Vous pouvez lier un événement à un widget particulier. Par exemple, vous pourriez lier la touche PageUp dans un canevas à un gestionnaire qui s’occuperait de le faire défiler d’une page vers le haut. Pour lier un événement à un widget, appelez la méthode bind() sur ce widget (voir Méthodes communes à tous les widgets).
Par exemple, supposez que vous ayez un canevas référencé par can et que vous souhaitiez dessiner un disque orange sur ce canevas à chaque fois que l’utilisateur appuie sur le bouton 2 de la souris (celui du milieu). Pour définir ce comportement:
can.bind('<Button-2>', dessineDisqueOrange)
Le premier argument, '<Button-2>', est un «descripteur de séquence» qui indique à tkinter que lorsque le bouton central de la souris est pressé, il faut qu’il appelle le gestionnaire d’événement dessineDisqueOrange fourni comme deuxième argument (Voir Écrire son gestionnaire: la classe Event, ci-dessous, pour une vue d’ensemble sur la manière d’écrire un gestionnaire comme dessineDisqueOrange). Notez qu’il faut omettre les parenthèses du gestionnaire d’événement afin que Python utilise la référence au gestionnaire plutôt que d’essayer de l’appeler sur le champ.
Liaison au niveau de l’application: Vous pouvez définir une liaison d’événement de telle sorte que le gestionnaire d’événement soit appelé indépendament du widget qui a le focus ou qui se trouve sous la souris. Par exemple, vous pourriez souhaiter lier l’événement « appui sur la touche ImprÉcran » à tous les widgets de l’applicatoin de telle sorte que l’écran soit imprimé indépendamment du widget qui a effectivement reçu l’appui sur la touche. Pour lier un événement au niveau de l’application, appeler la méthode bind_all() sur n’importe quel widget (voir Méthodes communes à tous les widgets).
Voici comment vous pourriez lier l’appui sur la touche, Key, ImprÉcran, Print, à l’effet désiré:
w.bind_all('<Key-Print>', imprimeEcran)
Tkinter dispose d’une méthode générale et puissante pour vous permettre d’indiquer précisément à quels événements vos gestionnaires sont liés.
En général, une séquence d’événements est une chaîne de caractères qui contient un ou plusieurs motifs d’événements. Chaque motif d’événements décrit quelquechose qui peut survenir pendant l’éxécution de votre application. S’il y a plus d’un motif dans une séquence d’événements, le gestionnaire associé sera appelé seulement si tous les motifs de la séquences se produisent en effet.
La forme générale d’un motif d’événement est la suivante:
<[modificateur-]...type[-detail]>
Voici quelques exemples de motifs d’événements:
Vous pouvez aussi utiliser des formes courtes pour préciser un événenemt. Voici quelques exemples:
'<1>' revient au même que '<Button-1>'.
'x' revient au même que '<KeyPress-x>'.
Remarquez que vous pouvez omettre les chevrons '<…>' pour la plupart des caractères, mais que vous ne pouvez pas le faire pour l’espace (dont le nom est '<space>') ou pour le caractère inférieur à < (dont le nom est '<less>').
L’ensemble complet de tous les types d’événements est très grand, mais beaucoup ne sont pas utilisés fréquemment. Voici la plupart de ceux dont vous aurez besoin:
Type | Nom | Description |
---|---|---|
36 | Activate | Un widget est passé de l’état inactif à l’état actif. Se rapporte au changement de l’option state des widgets comme un bouton qui est inactif (grisé) et devient actif. |
4 | Button | L’utilisateur a appuyé sur l’un des boutons de la souris. La partie détail précise le bouton. Pour la molette de la souris sous Linux, votre gestionnaire distinguera le défilement vers le haut et le défilement vers le bas en examinant l’attribut .num de l’instance d’événement qui lui est fourni; voir Écrire son gestionnaire: la classe Event. |
5 | ButtonRelease | L’utilisateur relâche un bouton de la souris. C’est probablement un meilleur choix dans la plupart des cas d’utiliser ce type d’événement plutôt que Button parce que si l’utilsateur appuie accidentellement sur le bouton, il peut bouger la souris en-dehors du widget pour éviter de lancer l’action. |
37 | Deactivate | Un widget est passé de l’état actif à l’état inactif. Se rapporte au changment de l’option state des widgets comme pour un bouton radio qui change d’état en devenant grisé. |
17 | Destroy | Un widget a été détruit. |
7 | Enter | L’utilisateur a bougé la souris qui est entrée dans la partie visible d’un widget. (Ne pas confondre avec la touche Entrée, qui est un événement de type KeyPress pour une touche dont le nom est 'Return'). |
2 | KeyPress | L’utilisateur a appuyé sur une touche du clavier. La partie détail précise optionnellement une touche en particulier. Ce mot clé peut être abrégé par Key. |
3 | KeyRelease | L’utilisateur a relâché une touche du clavier. |
8 | Leave | L’utilisateur a déplacé le pointeur de la souris en dehors d’un widget. |
6 | Motion | L’utilisateur a déplacé la souris à l’intérieur d’un widget. |
38 | MouseWheel | L’utilisateur a tourné la molette de la souris, vers le haut ou vers le bas. Pour l’instant, cela n’est pris en compte que par Windows ou MacOS, mais pas par Linux. Pour ces systèmes, voir la discussion de l’attribut delta d’une instance d’un objet de classe Event dans Écrire son gestionnaire: la classe Event. Pour Linux, se rapporter à la note ci-dessus pour le type Button. |
Les noms des modificateurs que vous pouvez utiliser dans une séquence d’événements sont, entre autres:
La partie detail d’un motif pour un événement KeyPress ou KeyRelease précise la touche que vous souhaitez surveiller. (Voir le modificateur Any ci-dessus si vous souhaitez surveiller toutes les touches).
Le tableau ci-dessous montre plusieurs façons de nommer les touches. Voir Écrire son gestionnaire: la classe Event, ci-dessous, pour plus d’informations sur les objets Event, dont les attributs décrivent les touches de la même manière)
Il y a beaucoup de noms de touches pour couvrir de nombreux ensembles de caractères internationaux. Ce tableau montre uniquement l’ensemble «Latin-1» pour un clavier type. Pour connaître l’ensemble des possibilités, reportez-vous à la page correspondante du manuel de Tk.
keysym | keycode | keysym_num | Touche |
---|---|---|---|
Alt_L | 64 | 65513 | La touche Alt située à gauche. |
BackSpace | 22 | 65288 | La touche Retour Arrière |
Cancel | 110 | 65387 | ??? |
Caps_Lock | 66 | 65509 | Verr Maj |
Control_L | 37 | 65507 | La touche Ctrl de gauche |
Control_R | 105 | 65508 | La touche Ctrl de droite |
Delete | 119 | 65535 | Suppr |
Down | 116 | 65364 | ↓ |
End | 115 | 65367 | Fin |
Escape | 9 | 65307 | Echap |
Execute | 111 | 65378 | ??? |
F1 | 67 | 65470 | La touche fonction F1 |
F2 | 68 | 65471 | La touche fonction F2 |
Fi | 66+i | 65469+i | La touche fonction Fi |
F12 | 96 | 65481 | La touche fonction F12 |
Home | 110 | 65360 | Début |
Insert | 118 | 65379 | Inser |
Left | 113 | 65361 | ← |
Linefeed | 54 | 106 | ??? Linefeed (control-J) |
KP_0 | 90 | 65456 | 0 sur le clavier numérique |
KP_1 | 87 | 65457 | 1 sur le clavier numérique |
KP_2 | 88 | 65458 | 2 sur le clavier numérique |
KP_3 | 89 | 65459 | 3 sur le clavier numérique |
KP_4 | 83 | 65460 | 4 sur le clavier numérique |
KP_5 | 84 | 65461 | 5 sur le clavier numérique |
KP_6 | 85 | 65462 | 6 sur le clavier numérique |
KP_7 | 79 | 65463 | 7 sur le clavier numérique |
KP_8 | 80 | 65464 | 8 sur le clavier numérique |
KP_9 | 81 | 65465 | 9 sur le clavier numérique |
KP_Add | 86 | 65451 | + sur le clavier numérique |
KP_Begin | 84 | 65437 | La touche centrale (même que 5) sur le clavier numérique |
KP_Decimal | 91 | 65454 | Symbole de la ponctuation décimale (,) sur le clavier numérique |
KP_Delete | 91 | 65439 | Suppr sur le clavier numérique |
KP_Divide | 106 | 65455 | / sur le clavier numérique |
KP_Down | 88 | 65433 | ↓ sur le clavier numérique |
KP_End | 87 | 65436 | Fin sur le clavier numérique |
KP_Enter | 104 | 65421 | Entrée sur le clavier numérique |
KP_Home | 79 | 65429 | Début sur le clavier numérique |
KP_Insert | 90 | 65438 | Insert sur le clavier numérique |
KP_Left | 83 | 65430 | ← sur le clavier numérique |
KP_Multiply | 63 | 65450 | × sur le clavier numérique |
KP_Next | 89 | 65435 | PageDown sur le clavier numérique |
KP_Prior | 81 | 65434 | PageUp sur le clavier numérique |
KP_Right | 85 | 65432 | → sur le clavier numérique |
KP_Subtract | 82 | 65453 | - sur le clavier numérique |
KP_Up | 80 | 65431 | ↑ sur le clavier numérique |
Next | 117 | 65366 | PageDown |
Num_Lock | 77 | 65407 | Verr Num |
Pause | 127 | 65299 | Pause |
111 | 65377 | ImprÉcran | |
Prior | 112 | 65365 | PageUp |
Return | 36 | 65293 | La touche Entrée (control-M). Le nom Enter se réfère à un événement associé à la souris et non au clavier; voir Types d’événements. |
Right | 114 | 65363 | → |
Scroll_Lock | 78 | 65300 | Verrouillage Défilement (ScrollLock) |
Shift_L | 50 | 65505 | La touche Maj de gauche |
Shift_R | 62 | 65506 | La touche Maj de droite |
space | 65 | 32 | La barre espace |
Tab | 23 | 65289 | La touche de Tabulation, Tab |
Up | 111 | 65362 | ↑ |
Les sections précédentes vous ont expliquées comment décrire l’événement auquel vous souhaitez réagir et comment le lier à l’application. À présent, intéressons-nous à l’écriture du gestionnaire d’événements qui sera appelé lorsque l’événement aura lieu.
Le gestionnaire d’événements recevra un objet de type Event qui sert à décrire les circonstances de l’événement. Le gestionnaire peut être une fonction ou une méthode. Voici la forme de la déclaration d’une fonction:
def nomGestionnaire(evt):
Et pour une méthode:
class MaClasse:
# ...
def nomGestionnaire(self, evt):
Les attributs de l’objet de type Event passé au gestionnaire, par l’intermédiaire de son paramètre evt (parfois noté plus explicitement event), sont décrits ci-dessous. Certains attributs possèdent toujours une valeur, mais d’autres n’en possède une que pour certains types d’événements.
char | Si l’événement est produit par l’appui ou le relâchement d’une touche qui produit un caractère ASCII régulier, cet attribut est le caractère sous la forme d’une chaîne. (Pour des touches spéciales comme Suppr, voir l’attribut keysym ci-dessous) |
delta | Pour un événement du type MouseWheel, cet attribut contient un entier dont le signe est positif pour un déplacement vers le haut, négatif pour un déplacement vers le bas. Sous Windows, cette valeur sera un multiple de 120; par exemple, 120 désigne un défilement vers le haut en une étape et -240 un défilement vers le bas en deux étapes. Sous MacOS, on aurait obtenu les valeurs 1 et -2 dans cet exemple. Pour le support de la molette sous Linux, voir les note sur l’événement de type Button dans Types d’événements. |
height | Si l’événement est du type Configure, cet attribut porte la nouvelle hauteur du widget en pixels. |
keycode | Pour un événement de type KeyPress ou KeyRelease, cet attribut contient le code de touche. Cependant, cet entier n’identifie pas quel caractère de la touche a été produit, ainsi «x» ou «X» ne se différencient pas par leur code de touche. Pour des valeurs possibles de cet attribut, voir Noms des touches. |
keysym | Pour un événement de type KeyPress ou KeyRelease impliquant une touche spéciale, cet attribut porte le nom de touche, par exemple 'Prior' pour la touche PageUp. Voir Noms des touches pour une liste complète des nom de touches. |
keysym_num | Pour un événement de type KeyPress ou KeyRelease, cet attribut est une version numérique de l’attribut keysym. Pour une touche régulière qui produit un seul caractère, cet attribut prend pour valeur le code ASCII du caractère. Pour des touches spéciales, référez-vous à Noms des touches. |
num | Si l’événement est associé à un bouton de la souris, cet attribut porte la valeur entière qui indique le numéro du bouton (1, 2 ou 3). Pour le support de la molette sous linux, lier les événements Button-4 et Button-5; lorsque la molette de la souris tourne vers l’avant, cet attribut prend la valeur 4, il prend la valeur 5 dans l’autre sens. |
serial | Un entier qui est incrémenté à chaque fois que le serveur répond à une requête du client. Vous pouvez utiliser cet attribut pour découvrir la séquence temporelle des événements: ceux qui ont eu lieu plus tôt ont une valeur plus petite. |
state | Un entier qui décrit l’état de toutes les touches modificatrice. Reportez-vous à la table des masques des modificateurs pour l’interprétation de cette valeur. |
time | Cet attribut porte un entier qui n’a pas de signification dans l’absolu, mais qui est incrémenté chaque milliseconde. Cela permet à votre application de déterminer, par exemple, le temps écoulé entre deux clic souris. |
type | Un code numérique qui décrit le type de l’événement. Pour l’interprétation de ce code, reportez-vous à Types d’événements. |
widget | Porte toujours la référence du widget qui a causé l’événement. Par exemple, si l’événement était un clic souris sur un canevas, cet attribut serait ce canevas. |
width | Si l’événement était du type Configure, cet attribut est la nouvelle largeur du widget en pixels. |
x | L’abscisse de la souris en pixels au moment de l’événement. Elle est relative au coin supérieur gauche du widget sur lequel se trouve la souris. |
y | Similaire à x mais dans la direction verticale. |
x_root | L’abscisse de la souris au moment où survient l’événement, relativement au coin supérieur gauche de l’écran. |
y_root | Similaire à x_root mais dans la direction verticale. |
Utilisez ces masques pour tester les bits de la valeur de l’attribut state pour savoir quel(s) touche(s) modificatrice(s) et/ou bouton(s) ont été utilisé(s) pendant l’événement.
Masque | Modificateur |
---|---|
0x0001 | Maj. |
0x0002 | Verr Maj. |
0x0004 | Control. |
0x0008 | Touche Alt de gauche. |
0x0010 | Verr Num. |
0x0080 | Touche Alt de droite. |
0x0100 | Bouton 1 de la souris. |
0x0200 | Bouton 2 de la souris. |
0x0400 | Bouton 3 de la souris. |
Voici un exemple de gestionnaire d’événements. Plus haut, dans Niveaux de liaisons, vous trouverez un exemple qui vous montre commment lier l’appui sur le bouton central de la souris à un gestionnaire nommé dessineDisqueOrange. Voici ce gestionnaire:
def dessineDisqueOrange(evt):
'''Dessine un disque orange là où se trouve la souris
'''
r = 5 # Son rayon
can.create_oval(evt.x-r, evt.y-r,
evt.x+r, evt.y+r, fill='orange')
Lorsque ce gestionnaire est appelé, la position courante de la souris est (evt.x, evt.y). La méthode create_oval() dessine un cercle dont la boîte englobante est un carré centré sur cette position et dont les côtés mesure 2*r.
Parfois, vous souhaiterez passer d’autres arguments à un gestionnaire (en plus de l’objet Event)
Voici un exemple. Supposez que votre application comporte un tableau de cases à cocher dont les widgets sont mémorisés dans une liste ccList, indexée par le numéro de la case à cocher situé dans range(10).
Supposez en outre que vous souhaitiez n’écrire qu’un gestionnaire ccGest pour l’événement '<Button-1>' sur l’une de ces 10 cases. Votre gestionnaire peut connaître la case sur laquelle a eu lieu le clic en utilisant l’attribut widget de l’objet Event, mais comment faire pour retrouver son index dans la liste ccList ?
Il serait commode d’écrire notre gestionnaire avec un argument supplémentaire pour le numéro de la case à cocher, quelquechose comme:
def ccGest(evt, ccNb):
Mais un gestionnaire d’événement ne reçoit qu’un argument, l’objet de type Event. Il n’est donc pas possible d’utiliser la fonction ci-dessus qui comporte un argument de trop.
Heureusement, il est possible d’exploiter les valeurs par défaut des fonctions pour parvenir à l’objectif. Observer le code suivant:
ccListe = []
def creerWidgets():
#...
for i in range(10):
cc = Checkbutton(root, ...)
ccList.append(cc)
cc.grid(row=1, column=i)
def gest(evt, i=i): 1
return ccGest(evt, i)
cc.bind('<Button-1>', gest)
#...
def ccGest(evt, ccNb):
#...
Ces lignes définissent un gestionnaire, gest() qui attend deux arguments. Le premier est l’objet de type Event habituel et le second a une valeur par défaut qui est exactement celle que nous avons besoin de connaître. Il suffit ensuite de définir le gestionnaire d’événement «réel», ccGest() pour atteindre le but que nous nous étions fixé.
Cette technique peut être étendue pour fournir autant d’arguments que souhaités à un gestionnaire d’événements.