0% ont trouvé ce document utile (0 vote)
5 vues11 pages

Introduction à Tkinter pour GUI Python

Ce chapitre présente l'utilisation de Tkinter pour créer des interfaces graphiques (GUI) en Python, soulignant l'importance de rendre les applications plus accessibles aux utilisateurs non familiers avec la ligne de commande. Il explique les concepts de widgets, de programmation événementielle, et de fonctions callback, qui sont essentiels pour interagir avec les éléments de l'interface. Des exemples pratiques sont fournis pour illustrer la création de fenêtres et de boutons simples, ainsi que l'utilisation de gestionnaires d'événements.

Transféré par

a.fabrici
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
5 vues11 pages

Introduction à Tkinter pour GUI Python

Ce chapitre présente l'utilisation de Tkinter pour créer des interfaces graphiques (GUI) en Python, soulignant l'importance de rendre les applications plus accessibles aux utilisateurs non familiers avec la ligne de commande. Il explique les concepts de widgets, de programmation événementielle, et de fonctions callback, qui sont essentiels pour interagir avec les éléments de l'interface. Des exemples pratiques sont fournis pour illustrer la création de fenêtres et de boutons simples, ainsi que l'utilisation de gestionnaires d'événements.

Transféré par

a.fabrici
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

CHAPITRE 25

Fenêtres graphiques et Tkinter

Conseil
Dans ce chapitre, nous allons utiliser des classes, nous vous conseillons de bien relire les chapitres 23 Avoir la classe
avec les objets et 24 Avoir plus la classe avec les objets (en ligne). Par ailleurs, nous vous conseillons de relire également
la rubrique Arguments positionnels et arguments par mot-clé du chapitre 10 sur les fonctions.

25.1 Utilité d’une GUI


Dans votre carrière « pythonesque » il se peut que vous soyez amené à vouloir développer une application graphique,
on parle encore de graphical user interface ou GUI. Jusqu’à maintenant, vous avez fait en sorte qu’un utilisateur interagisse
avec votre code via la ligne de commande, par exemple :
$ python mon_script.py [Link] blabla blublu

Les arguments passés à la ligne de commande sont tout à fait classiques dans le monde de la bioinformatique. Toutefois,
il se peut que vous développiez un programme pour une communauté plus large, qui n’a pas forcément l’habitude d’utiliser
un shell et la ligne de commande. Une GUI permettra un usage plus large de votre programme, il est donc intéressant
de regarder comment s’y prendre. Dans notre exemple ci-dessus on pourrait par exemple développer une interface où
l’utilisateur choisirait le nom du fichier d’entrée par l’intermédiaire d’une boîte de dialogue, et de contrôler les options en
cliquant sur des boutons, ou des « listes de choix ». Une telle GUI pourrait ressembler à la figure 25.1.
Au delà de l’aspect convivial pour l’utilisateur, vous pourrez, avec une GUI, construire des fenêtres illustrant des
éléments que votre programme génère à la volée. Ainsi, vous « verrez » ce qui se passe de manière explicite et en direct !
Par exemple, si on réalise une simulation de particules, on a envie de voir un « film » des particules en mouvement, c’est-
à-dire comment ces particules bougent au fur et à mesure que les pas de simulation avancent. Une GUI vous permettra
une telle prouesse ! Enfin, sachez que certains logiciels scientifiques ont été développés avec la bibliothèque graphique Tk
(par exemple pymol, vmd, etc.). Qui sait, peut-être serez-vous le prochain développeur d’un outil incontournable ?
Il existe beaucoup de modules pour construire des applications graphiques. Par exemple : Tkinter 1 , wxpython 2 , PyQt 3 ,

1. [Link]
2. [Link]
3. [Link]

300
25.2. Quelques concepts liés à la programmation graphique Chapitre 25. Fenêtres graphiques et Tkinter

Figure 25.1 – Exemple de GUI.

PyGObject 4 , etc. Nous présentons dans ce chapitre le module Tkinter qui est présent de base dans les distributions Python
(pas besoin a priori de faire d’installation de module externe). Tkinter permet de piloter la bibliothèque graphique Tk
(Tool Kit), Tkinter signifiant tk interface. On pourra noter que cette bibliothèque Tk peut être également pilotée par
d’autres langages (Tcl, perl, etc.).

25.2 Quelques concepts liés à la programmation graphique


Lorsque l’on développe une GUI, nous créons une fenêtre graphique contenant notre application, ainsi que des widgets
inclus dans la fenêtre.

Définition
Les widgets (window gadget) sont des objets graphiques permettant à l’utilisateur d’interagir avec votre programme
Python de manière conviviale. Par exemple, dans la fenêtre sur la figure 25.1, les boutons, les listes de choix, ou encore
la zone de texte sont des widgets.

L’utilisation d’une GUI va amener une nouvelle manière d’aborder le déroulement d’un programme, il s’agit de la
programmation dite « événementielle ». Jusqu’à maintenant vous avez programmé « linéairement », c’est-à-dire que
les instructions du programme principal s’enchaînaient les unes derrière les autres (avec bien sûr de possibles appels à
des fonctions). Avec une GUI, l’exécution est décidée par l’utilisateur en fonction de ses interactions avec les différents
widgets. Comme c’est l’utilisateur qui décide quand et où il clique dans l’interface, il va falloir mettre en place ce qu’on
appelle un « gestionnaire d’événements ».

Définition
Le gestionnaire d’événements est une sorte de « boucle infinie » qui est à l’affût de la moindre action de la part de
l’utilisateur. C’est lui qui effectuera une action lors de l’interaction de l’utilisateur avec chaque widget de la GUI. Ainsi,
l’exécution du programme sera réellement guidée par les actions de l’utilisateur.

La bibliothèque Tk que nous piloterons avec le module Python Tkinter propose tous les éléments cités ci-dessus (fe-
nêtre graphique, widgets, gestionnaire d’événements). Nous aurons cependant besoin d’une dernière notion : les fonctions
callback.

Définition
4. [Link]

Cours de Python / Université Paris Cité / UFR Sciences du Vivant 301


Chapitre 25. Fenêtres graphiques et Tkinter 25.3. Notion de fonction callback

Une fonction callback est une fonction passée en argument d’une autre fonction.

Un exemple de fonction callback est présenté dans la rubrique suivante.

25.3 Notion de fonction callback

Conseil
Si vous êtes débutant, vous pouvez sauter cette rubrique.

Jusqu’à maintenant nous avons toujours appelé les fonctions ou les méthodes de cette manière :
1 var = fct(arg1, arg2)
2
3 [Link](arg)

où les arguments étaient des objets « classiques » (par exemple une chaîne de caractères, un entier, un float, etc.).
Sachez qu’il est possible de passer en argument une fonction à une autre fonction ! Par exemple :
1 def fct_callback(arg):
2 print(f"J'aime bien les {arg} !")
3
4
5 def une_fct(ma_callback):
6 print("Je suis au début de une_fct(), "
7 "et je vais exécuter la fonction callback :")
8 ma_callback("fraises")
9 print("une_fct() se termine.")
10
11 if __name__ == "__main__":
12 une_fct(fct_callback)

Si on exécute ce code, on obtient :


Je suis au début de une_fct() et je vais exécuter la fonction callback :
J'aime bien les fraises !
une_fct() se termine.

Vous voyez que dans le programme principal, lors de l’appel de une_fct(), on lui passe comme argument une autre
fonction mais sans aucune parenthèses ni argument, c’est-à-dire fct_callback tout court. En d’autres termes, cela
est différent de
une_fct(fct_callback("scoubidous")).
Dans une telle construction, fct_callback("scoubidous") serait d’abord évaluée, puis ce serait la valeur ren-
voyée par cet appel qui serait passée à une_fct() (n’essayez pas sur notre exemple car cela mènerait à une erreur !).
Que se passe-t-il en filigrane lors de l’appel une_fct(fct_callback) ? Python passe une référence vers la fonction
fct_callback (en réalité il s’agit d’un pointeur, mais tout ceci est géré par Python et est transparent pour l’utilisateur).
Vous souvenez-vous ce qui se passait avec une liste passée en argument à une fonction (voir le chapitre 13 Plus sur les
fonctions) ? C’était la même chose, une référence était envoyée plutôt qu’une copie. Python Tutor 5 nous confirme cela
(cf. figure 25.2).
Lorsqu’on est dans une_fct() on pourra utiliser bien sûr des arguments lors de l’appel de notre fonction callback
si on le souhaite. Notez enfin que dans une_fct() la fonction callback reçue en argument peut avoir un nom différent
(comme pour tout type de variable).
À quoi cela sert-il ? À première vue cette construction peut sembler ardue et inutile. Toutefois, vous verrez que dans
le module Tkinter les fonctions callback sont incontournables. En effet, on utilise cette construction pour lancer une
fonction lors de l’interaction de l’utilisateur avec un widget : par exemple, lorsque l’utilisateur clique sur un bouton et
qu’on souhaite lancer une fonction particulière suite à ce clic. Notez enfin que nous les avons déjà croisées avec :

5. [Link]

302 Cours de Python / Université Paris Cité / UFR Sciences du Vivant


25.4. Prise en main du module Tkinter Chapitre 25. Fenêtres graphiques et Tkinter

Figure 25.2 – Exemple de fonction callback dans Python Tutor.

• le tri de dictionnaire par valeur avec la syntaxe sorted(dico, key=[Link]) (voir le chapitre 8 Dictionnaires
et tuples) ;
• le tri par longueur de mots avec la syntaxe sorted(liste, key=len) (voir chapitre 12 Plus sur les listes) ;
• les objets property avec la syntaxe property(fget=get_masse, fset=set_masse) (voir le chapitre 24 Avoir
plus la classe avec les objets (en ligne)).

25.4 Prise en main du module Tkinter


Le module Tkinter est très vaste. Notre but n’est pas de vous faire un cours exhaustif mais plutôt de vous montrer
quelques pistes. Pour apprendre à piloter ce module, nous pensons qu’il est intéressant de vous montrer des exemples. Nous
allons donc en présenter quelques-uns qui pourraient vous être utiles, à vous ensuite de consulter de la documentation
supplémentaire si vous souhaitez aller plus loin (cf. la rubrique Bibliographie pour aller plus loin).

25.4.1 Un premier exemple dans l’interpréteur


Commençons par construire un script qui affichera une simple fenêtre avec un message et un bouton. Regardons
d’abord comment faire dans l’interpréteur (nous vous conseillons de tester ligne par ligne ce code tout en lisant les
commentaires ci-dessous) :
1 >>> import tkinter as tk
2 >>> racine = [Link]()
3 >>> label = [Link](racine, text="J'adore Python !")
4 >>> bouton = [Link](racine, text="Quitter", fg="red",
5 ... command=[Link])
6 >>> [Link]()
7 >>> [Link]()
8 >>>

Ligne 2. On crée la fenêtre principale (vous la verrez apparaître !). Pour cela, on crée une instance de la classe [Link]
dans la variable racine. Tous les widgets que l’on créera ensuite seront des fils de cette fenêtre. On pourra d’ailleurs
noter que cette classe [Link] ne s’instancie en général qu’une seule fois par programme. Vous pouvez, par curiosité, lancer
une commande dir(racine) ou help(racine), vous verrez ainsi les très nombreuses méthodes et attributs associés à
un tel objet Tk.
Ligne 3. On crée un label, c’est-à-dire une zone dans la fenêtre principale où on écrit un texte. Pour cela, on a créé
une variable label qui est une instance de la classe [Link]. Cette variable label contient donc notre widget, nous la
réutiliserons plus tard (par exemple pour placer ce widget dans la fenêtre). Notez le premier argument positionnelracine
passé à la classe [Link], celui-ci indique la fenêtre parente où doit être dessinée le label. Cet argument doit toujours
être passé en premier et il est vivement conseillé de le préciser. Nous avons passé un autre argument avec le nom
text pour indiquer, comme vous l’avez deviné, le texte que nous souhaitons voir dans ce label. La classe [Link]
peut recevoir de nombreux autres arguments, en voici la liste exhaustive 6 . Dans les fonctions Tkinter qui construisent
6. [Link]

Cours de Python / Université Paris Cité / UFR Sciences du Vivant 303


Chapitre 25. Fenêtres graphiques et Tkinter 25.4. Prise en main du module Tkinter

un widget, les arguments possibles pour la mise en forme de celui-ci sont nombreux, si bien qu’ils sont toujours des
arguments par mot-clé. Si on ne précise pas un de ces arguments lors de la création du widget, l’argument prendra
alors une valeur par défaut. Cette liste des arguments par mot-clé est tellement longue qu’en général on ne les précisera
pas tous. Heureusement, Python autorise l’utilisation des arguments par mot-clé dans un ordre quelconque. Comme nous
l’avons vu dans le chapitre 10 Fonctions, souvenez vous que leur utilisation dans le désordre implique qu’il faudra toujours
préciser leur nom : par exemple vous écrirez text="blabla" et non pas "blabla" tout court.
Ligne 4. De même, on crée un bouton « Quitter » qui provoquera la fermeture de la fenêtre et donc l’arrêt de
l’application si on clique dessus. À nouveau, on passe la fenêtre parente en premier argument, le texte à écrire dans le
bouton, puis la couleur de ce texte. Le dernier argument command=[Link] va indiquer la fonction / méthode
à exécuter lorsque l’utilisateur clique sur le bouton. On pourra noter que l’instance de la fenêtre mère [Link] (que nous
avons nommée racine) possède une méthode .destroy() qui va détruire le widget sur lequel elle s’applique. Comme
on tue la fenêtre principale (que l’on peut considérer comme un widget contenant d’autres widgets), tous les widgets
fils seront détruits et donc l’application s’arrêtera. Vous voyez par ailleurs que cette méthode [Link] est
passée à l’argument command= sans parenthèses ni arguments : il s’agit donc d’une fonction callback comme expliqué
ci-dessus. Dans tous les widgets Tkinter, on doit passer à l’argument command=... une fonction / méthode callback.
La liste exhaustive des arguments possibles de la classe [Link] se trouve ici 7 .
Lignes 6 et 7. Vous avez noté que lors de la création de ce label et de ce bouton, rien ne s’est passé dans la fenêtre.
C’est normal, ces deux widgets existent bien, mais il faut maintenant les placer à l’intérieur de la fenêtre. On appelle pour
ça la méthode .pack(), avec une notation objet [Link]() : à ce moment précis, vous verrez votre label apparaître
ainsi que la fenêtre qui se redimensionne automatiquement en s’adaptant à la grandeur de votre label. L’invocation de la
même méthode pour le bouton va faire apparaître celui-ci juste en dessous du label et redimensionner la fenêtre. Vous
l’aurez compris la méthode .pack() place les widgets les uns en dessous des autres et ajuste la taille de la fenêtre. On
verra plus bas que l’on peut passer des arguments à cette méthode pour placer les widgets différemment (en haut, à
droite, à gauche).
Au final, vous devez obtenir une fenêtre comme sur la figure 25.3.

25.4.2 Le même exemple dans un script.


Tentons maintenant de faire la même chose dans un script tk_exemple.py :
1 import tkinter as tk
2
3 racine = [Link]()
4 label = [Link](racine, text="J'adore Python !")
5 bouton = [Link](racine, text="Quitter", command=[Link])
6 bouton["fg"] = "red"
7 [Link]()
8 [Link]()
9 [Link]()
10 print("C'est fini !")

puis lançons ce script depuis un shell :


$ python tk_exemple.py

Vous voyez maintenant la même fenêtre avec les mêmes fonctionnalités par rapport à la version dans l’interpréteur
(voir la figure 25.3). Nous commentons ici les différences (dans le désordre) :
Ligne 6. Le bouton a été créé en ligne 5, mais on voit qu’il est possible de préciser une option de rendu du widget
après cette création (ici on met le texte en rouge avec l’option "fg"). La notation ressemble à celle d’un dictionnaire
avec une syntaxe générale widget["option"] = valeur.
Ligne 9. L’instruction [Link]() va lancer le gestionnaire d’événements que nous avons évoqué ci-dessus.
C’est lui qui interceptera la moindre action de l’utilisateur, et qui lancera les portions de code associées à chacune de ses
actions. Bien sûr, comme nous développerons dans ce qui va suivre toutes nos applications Tkinter dans des scripts (et
non pas dans l’interpréteur), cette ligne sera systématiquement présente. Elle sera souvent à la fin du script, puisque, à
l’image de ce script, on écrit d’abord le code construisant l’interface, et on lance le gestionnaire d’événements une fois
l’interface complètement décrite, ce qui lancera au final l’application.
7. [Link]

304 Cours de Python / Université Paris Cité / UFR Sciences du Vivant


25.5. Construire une application Tkinter avec une classe Chapitre 25. Fenêtres graphiques et Tkinter

Ligne 10. Cette ligne ne s’exécute qu’après l’arrêt de l’application (soit en cliquant sur le bouton « Quitter », soit en
cliquant sur la croix).
Ligne 5. Pour quitter l’application, on utilise ici la méthode .quit(). Celle-ci casse la .mainloop() et arrête ainsi
le gestionnaire d’événements. Cela mène à l’arrêt de l’application. Dans le premier exemple dans l’interpréteur, on avait
utilisé la méthode .destroy() sur la fenêtre principale. Comme son nom l’indique, celle-ci détruit la fenêtre principale
et mène aussi à l’arrêt de l’application. Cette méthode aurait donc également fonctionné ici. Par contre, la méthode
.quit() n’aurait pas fonctionné dans l’interpréteur car, comme on l’a vu, la boucle .mainloop() n’y est pas présente.
Comme nous écrirons systématiquement nos applications Tkinter dans des scripts, et que la boucle .mainloop() y est
obligatoire, vous pourrez utiliser au choix .quit() ou .destroy() pour quitter l’application.

Figure 25.3 – Exemple basique de fenêtre Tkinter.

25.5 Construire une application Tkinter avec une classe


De manière générale, il est vivement conseillé de développer ses applications Tkinter en utilisant une classe. Cela
présente l’avantage d’encapsuler l’application de manière efficace et d’éviter ainsi l’utilisation de variables globales.
Souvenez-vous, elles sont à bannir définitivement ! Une classe crée un espace de noms propre à votre application, et
toutes les variables nécessaires seront ainsi des attributs de cette classe. Reprenons notre petit exemple avec un label et
un bouton :
1 import tkinter as tk
2
3 class Application([Link]):
4 def __init__(self):
5 [Link].__init__(self)
6 self.creer_widgets()
7
8 def creer_widgets(self):
9 [Link] = [Link](self, text="J'adore Python !")
10 [Link] = [Link](self, text="Quitter", command=[Link])
11 [Link]()
12 [Link]()
13
14
15 if __name__ == "__main__":
16 app = Application()
17 [Link]("Ma Première App :-)")
18 [Link]()

Ligne 3. On crée notre application en tant que classe. Notez que cette classe porte un nom qui commence par
une majuscule (comme recommandé dans les bonnes pratiques de la PEP8 8 , voir le chapitre 16 Bonnes pratiques en
programmation Python). L’argument passé dans les parenthèses indique que notre classe Application hérite de la
classe [Link]. Par ce mécanisme, nous héritons ainsi de toutes les méthodes et attributs de cette classe mère, mais nous
pouvons en outre en ajouter de nouvelles/nouveaux (on parle aussi de « redéfinition » de la classe [Link]) !
Ligne 4. On crée un constructeur, c’est-à-dire une méthode qui sera exécutée lors de l’instanciation de notre classe
(à la ligne 16).
Ligne 5. On appelle ici le constructeur de la classe mère [Link].__init__(). Pourquoi fait-on cela ? On se souvient
dans la version linéaire de l’application, on avait utilisé une instanciation classique : racine = [Link](). Ici, l’effet de
l’appel du constructeur de la classe mère permet d’instancier la fenêtre Tk dans la variable self directement. C’est-à-dire
que la prochaine fois que l’on aura besoin de cette instance (lors de la création des widgets par exemple, cf. lignes 9 et

8. [Link]

Cours de Python / Université Paris Cité / UFR Sciences du Vivant 305


Chapitre 25. Fenêtres graphiques et Tkinter 25.6. Le widget canvas

10), on utilisera directement self plutôt que racine ou tout autre nom donné à l’instance. Comme vu dans le chapitre
23 Avoir la classe avec les objets, appeler le constructeur de la classe mère est une pratique classique lorsqu’une classe
hérite d’une autre classe.
Ligne 6. On appelle la méthode self.creer_widgets() de notre classe Application. Pour rappel, le self avant
le .creer_widgets() indique qu’il s’agit d’une méthode de notre classe (et non pas d’une fonction classique).
Ligne 8. La méthode .creer_widgets() va créer des widgets dans l’application.
Ligne 9. On crée un label en instanciant la classe [Link](). Notez que le premier argument passé est maintenant
self (au lieu de racine précédemment) indiquant la fenêtre dans laquelle sera construit ce widget.
Ligne 10. De même on crée un widget bouton en instanciant la classe [Link](). Là aussi, l’appel à la méthode
.quit() se fait par [Link] puisque la fenêtre est instanciée dans la variable self. Par ailleurs, on ne met ni
parenthèses ni arguments à [Link] car il s’agit d’une fonction callback (comme dans la rubrique précédente).
Lignes 11 et 12. On place les deux widgets dans la fenêtre avec la méthode .pack().
Ligne 15. Ici on autorise le lancement de notre application Tkinter en ligne de commande (python tk_application.
py), ou bien de réutiliser notre classe en important tk_application.py en tant que module (import tk_application
) (voir le chapitre 15 Création de modules).
Ligne 16. On instancie notre application.
Ligne 17. On donne un titre dans la fenêtre de notre application. Comme on utilise de petits widgets avec la méthode
pack(), il se peut que le titre ne soit pas visible lors du lancement de l’application. Toutefois, si on « étire » la fenêtre
à la souris, le titre le deviendra. On pourra noter que cette méthode .title() est héritée de la classe mère Tk.
Ligne 18. On lance le gestionnaire d’événements.
Au final, vous obtiendrez le même rendu que précédemment (cf. figure 25.3). Alors vous pourrez-vous poser la
question, « pourquoi ai-je besoin de toute cette structure alors que le code précédent semblait plus direct ? ». La réponse
est simple, lorsqu’un projet de GUI grossit, le code devient très vite illisible s’il n’est pas organisé en classe. De plus,
la non-utilisation de classe rend quasi-obligatoire l’utilisation de variables globales, ce qui on l’a vu, est à proscrire
définitivement ! Dans la suite du chapitre, nous verrons quelques exemples qui illustrent cela (cf. la rubrique suivante).

25.6 Le widget canvas


25.6.1 Un canvas simple et le système de coordonnées
Le widget canvas 9 de Tkinter est très puissant. Il permet de dessiner des formes diverses (lignes, cercles, etc.), et
même de les animer !
La classe [Link] crée un widget canvas (ou encore canevas en français). Cela va créer une zone (i.e. le canevas
en tant que tel) dans laquelle nous allons dessiner divers objets tels que des ellipses, lignes, polygones, etc., ou encore
insérer du texte ou des images. Regardons tout d’abord un code minimal qui construit un widget canvas, dans lequel on
y dessine un cercle et deux lignes :
1 import tkinter as tk
2
3 racine = [Link]()
4 canv = [Link](racine, bg="white", height=200, width=200)
5 [Link]()
6 canv.create_oval(0, 0, 200, 200, outline="red", width=10)
7 canv.create_line(0, 0, 200, 200, fill="black", width=10)
8 canv.create_line(0, 200, 200, 0, fill="black", width=10)
9 [Link]()

Ligne 4. On voit qu’il faut d’abord créer le widget canvas, comme d’habitude en lui passant l’instance de la fenêtre
principale en tant qu’argument positionnel, puis les options. Notons que nous lui passons comme options la hauteur et la
largeur du canvas. Même s’il s’agit d’arguments par mot-clé, donc optionnels, c’est une bonne pratique de les préciser.
En effet, les valeurs par défaut risqueraient de nous mener à dessiner hors de la zone visible (cela ne génère pas d’erreur
mais n’a guère d’intérêt).
Ligne 6 à 8. Nous dessinons maintenant des objets graphiques à l’intérieur du canevas avec les méthodes .create_oval
() (dessine une ellipse) et .create_line() (dessine une ligne). Les arguments positionnels sont les coordonnées de

9. [Link]

306 Cours de Python / Université Paris Cité / UFR Sciences du Vivant


25.6. Le widget canvas Chapitre 25. Fenêtres graphiques et Tkinter

l’ellipse (les deux points englobant l’ellipse, cf. ce lien 10 pour la définition exacte) ou de la ligne. Ensuite, on passe comme
d’habitude des arguments par mot-clé (vous commencez à avoir l’habitude !) pour mettre en forme ces objets graphiques.

Le rendu de l’image est montré dans la figure 25.4 ainsi que le système de coordonnées associé au canvas. Comme
dans la plupart des bibliothèques graphiques, l’origine du repère du canvas (i.e. la coordonnée (0,0)) est en haut à gauche.
Les x vont de gauche à droite, et les y vont de haut en bas.

Figure 25.4 – Exemple 1 de canvas avec le système de coordonnées. Le système de coordonnées est montré en vert et
n’apparaît pas sur la vraie fenêtre Tkinter.

Attention

L’axe des y est inversé par rapport à ce que l’on représente en mathématique. Si on souhaite représenter une fonction
mathématique (ou tout autre objet dans un repère régi par un repère mathématique), il faudra faire un changement de
repère.

25.6.2 Un canvas encapsulé dans une classe

Voici un exemple un peu plus conséquent d’utilisation du widget canvas qui est inclus dans une classe. Il s’agit d’une
application dans laquelle il y a une zone de dessin, un bouton dessinant des cercles, un autre des lignes et un dernier
bouton qui quitte l’application (figure 25.5).

Le code suivant crée une telle application :

10. [Link]

Cours de Python / Université Paris Cité / UFR Sciences du Vivant 307


Chapitre 25. Fenêtres graphiques et Tkinter 25.6. Le widget canvas

Figure 25.5 – Exemple 2 de canvas.

1 import tkinter as tk
2 import random as rd
3
4 class AppliCanevas([Link]):
5 def __init__(self):
6 [Link].__init__(self)
7 [Link] = 500
8 self.creer_widgets()
9
10 def creer_widgets(self):
11 # création canevas
12 [Link] = [Link](self, bg="light gray", height=[Link],
13 width=[Link])
14 [Link](side=[Link])
15 # boutons
16 self.bouton_cercles = [Link](self, text="Cercle !",
17 command=self.dessine_cercles)
18 self.bouton_cercles.pack(side=[Link])
19 self.bouton_lignes = [Link](self, text="Lignes !",
20 command=self.dessine_lignes)
21 self.bouton_lignes.pack()
22 self.bouton_quitter = [Link](self, text="Quitter",
23 command=[Link])
24 self.bouton_quitter.pack(side=[Link])
25
26 def rd_col(self):
27 return [Link](("black", "red", "green", "blue", "yellow", "magenta",
28 "cyan", "white", "purple"))
29
30 def dessine_cercles(self):
31 for i in range(20):
32 x, y = [[Link](1, [Link]) for j in range(2)]
33 diameter = [Link](1, 50)
34 [Link].create_oval(x, y, x+diameter, y+diameter,
35 fill=self.rd_col())
308 36 Cours de Python / Université Paris Cité / UFR Sciences du Vivant
37 def dessine_lignes(self):
38 for i in range(20):
25.6. Le widget canvas Chapitre 25. Fenêtres graphiques et Tkinter

Lignes 4 à 6. Comme montré dans la rubrique Construire une application Tkinter avec une classe, notre classe
AppliCanevas hérite de la classe générale [Link] et la fenêtre Tk se retrouve dans la variable self.

Ligne 7. On crée un attribut de la classe [Link] qui contiendra la taille (hauteur et largeur) du canvas. On
rappelle que cet attribut sera visible dans l’ensemble de la classe puisqu’il est « accroché » à celle-ci par le self.

Ligne 8. On lance la méthode .creer_widgets() (qui est elle aussi « accrochée » à la classe par le self).

Lignes 12 à 14. On crée un widget canvas en instanciant la classe [Link]. On place ensuite le canvas dans la
fenêtre avec la méthode .pack() en lui précisant où le placer avec la variable Tkinter [Link].

Lignes 15 à 24. On crée des widgets boutons et on les place dans la fenêtre. À noter que chacun de ces widgets appelle
une méthode différente, dont deux que nous avons créées dans la classe (.dessine_cercle() et .dessine_lignes()).

Ligne 26 à 28. Cette méthode renvoie une couleur au hasard sous forme de chaîne de caractères.

Lignes 30 à 40. On définit deux méthodes qui vont dessiner des paquets de 20 cercles (cas spécial d’une ellipse) ou 20
lignes aléatoires. Lors de la création de ces cercles et lignes, on ne les récupère pas dans une variable car on ne souhaite
ni les réutiliser ni changer leurs propriétés par la suite. Vous pourrez noter ici l’avantage de programmer avec une classe,
le canvas est directement accessible dans n’importe quelle méthode de la classe avec [Link] (pas besoin de le passer
en argument ou de créer une variable globale).

25.6.3 Un canvas animé dans une classe

Dans ce dernier exemple, nous allons illustrer la puissance du widget canvas en vous montrant que l’on peut animer
les objets se trouvant à l’intérieur. Nous allons également découvrir une technique intéressante, à savoir, comment «
intercepter » des clics de souris générés ou des touches pressées par l’utilisateur. L’application consiste en une « baballe
» qui se déplace dans la fenêtre et dont on contrôle les propriétés à la souris (cf. figure 25.6). Vous pouvez télécharger
le script ici 11 .

11. [Link]

Cours de Python / Université Paris Cité / UFR Sciences du Vivant 309


Chapitre 25. Fenêtres graphiques et Tkinter 25.6. Le widget canvas

1 """Super appli baballe !!!


2
3 Usage: python tk_baballe.py
4 - clic gauche: faire grossir la baballe
5 - clic droit: faire rétrécir la baballe
6 - clic central: relance la baballe (depuis le point du clic)
7 dans une direction aléatoire
8 - touche Esc: quitte l'appli baballe
9 """
10
11 import tkinter as tk
12 import random as rd
13
14 class AppliBaballe([Link]):
15 def __init__(self):
16 """Constructeur de l'application."""
17 [Link].__init__(self)
18 # Coord baballe.
19 self.x, self.y = 200, 200
20 # Rayon baballe.
21 [Link] = 50
22 # Pas de deplacement.
23 [Link], [Link] = 20, 20
24 # Création et packing du canvas.
25 [Link] = [Link](self, bg='light gray', height=400, width=400)
26 [Link]()
27 # Création de la baballe.
28 [Link] = [Link].create_oval(self.x, self.y,
29 self.x+[Link],
30 self.y+[Link],
31 width=2, fill="blue")
32 # Binding des actions.
33 [Link]("<Button-1>", [Link])
34 [Link]("<Button-2>", [Link])
35 [Link]("<Button-3>", [Link])
36 [Link]("<Escape>", [Link])
37 # Lancer la baballe.
38 [Link]()
39
40 def move(self):
41 """Déplace la baballe (appelée itérativement avec la méthode after)."""
42 # Incrémente coord baballe.
43 self.x += [Link]
44 self.y += [Link]
45 # Vérifier que la baballe ne sort pas du canvas (choc élastique).
46 if self.x < 10:
47 [Link] = abs([Link])
48 if self.x > [Link]-10:
49 [Link] = -abs([Link])
50 if self.y < 10:
51 [Link] = abs([Link])
52 if self.y > [Link]-10:
53 [Link] = -abs([Link])
54 # Mise à jour des coord.
55 [Link]([Link], self.x, self.y, self.x+[Link],
56 self.y+[Link])
57 # Rappel de move toutes les 50ms.
58 [Link](50, [Link])
59
60 def boom(self, mclick):
61 """Relance la baballe dans une direction aléatoire au point du clic."""
62 self.x = mclick.x
63 self.y = mclick.y
64 [Link].create_text(self.x, self.y, text="Boom !", fill="red")
65 [Link] = [Link]([-30, -20, -10, 10, 20, 30])
66 [Link] = [Link]([-30, -20, -10, 10, 20, 30])
67
68 def incr(self, lclick):
69 """Augmente la taille de la baballe."""
70 [Link] += 10
71 if [Link] > 200:
72 [Link] = 200
73
74 def decr(self, rclick):
310 Cours de Python / Université Paris Cité / UFR Sciences du Vivant
75 """Diminue la taille de la baballe."""
76 [Link] -= 10
77 if [Link] < 10:

Vous aimerez peut-être aussi