python tkinter

Identification

Infoforall

Fiche Tkinter pour Python


Fiche qui précise comment créer des fenêtre basiques avec la bibliothèque tkinter.

D'autres fiches tkinter permettront de détailler d'autres aspects.

Ici, on part à l'essentiel pour réaliser une application comportant des zones qu'on peut colorer, sur lesquelles on peut écrire et cliquer pour provoquer des effets.

1 - Fenêtre d'application

tkinter est le nom d'une des bibliothèques qui permet de réaliser des interfaces graphiques. Il ne s'agit pas de la plus performante, de la plus jolie mais elle a l'intêret d'être assez présente sur le Web. On peut ainsi trouver beaucoup d'exemples assez facilement. Et de ne pas être trop complexe à prendre en main pour réaliser de petites applications non profesionnelles.

Le module est installé de base avec les versions Python disponibles sous Windows.

Voici un code basique permettant de créer une fenêtre graphique :

1 2 3 4 5 6 7 8
import tkinter as tk # Création de la fenêtre du logiciel fenetre = tk.Tk() # Configuration de la fenêtre fenetre.geometry("600x300") fenetre.title("Ma super application") fenetre.configure(bg="black")
  • L1 : Importation du module
  • L4 : Création d'un objet-fenêtre à partir de la classe Tk.
  • L6 : Choix des dimensions de la fenêtre. On remarquera qu'on donne les dimensions de la fenêtre en pixels sous forme d'un string. On donne d'abord la largeur (600 pixels) puis la hauteur (300 pixels).
  • L7 : Choix du titre de la fenêtre visible dans la barre supérieure
  • L8 : Choix du fond coloré (bg stands for background). On donne la couleur sous forme d'un string. On peut donner une couleur prédéfinie ou la choisir en utilisant les trois intensités RGB sous forme hexadécimale #RRGGBB.

Les intensités hexadécimales varient entre 00 (la plus faible) et FF, la plus forte.

Exemple : rouge intense

fenetre.configure(bg="#FF0000")

Exemple : rouge foncé

fenetre.configure(bg="#880000")

Exemple : jaune

fenetre.configure(bg="#FFFF00")

On constate bien qu'on obtient du jaune par synthèse additive du rouge et du vert.

Comme il s'agit d'une interface graphique, le principe est de passer en programmation événementielle et donc de surveiller les événements (clicks sur l'écran, touches claviers activées ...)

La dernière ligne de votre application graphique sera toujours fenetre.mainloop() ou équivalent.

1 2 3 4 5 6 7 8 9 10 11
import tkinter as tk # Création de la fenêtre du logiciel fenetre = tk.Tk() # Configuration de la fenêtre fenetre.geometry("600x300") fenetre.title("Ma super application") fenetre.configure(bg="black") # Surveillance des événements fenetre.mainloop()

La méthode mainloop permet de lancer la surveillance des événements. Loop signifie bouclage, et main signifie principal.

2 - Widget Label

Le mot widget est la contraction de window et de gadget.

Création

Les widgets sont des objets et sont donc créés en utilisant un constructeur nommé Label.

monLabel = tk.Label(fenetre, ...)

Le premier paramètre à fournir est la référence d'un objet de type Tk. Ici, je donne donc fenetre puisqu'il s'agit du nom de la variable contenant la référence de ma fenêtre.

Les autres paramètres nommés possibles sont :

  • text : le texte qu'on veut voir s'afficher dans le widget. Exemple text="bonjour"
  • fg : le foreground, la couleur de premier plan : la couleur du texte. Exemple fg="white".
  • bg : le background, la couleur d'arrière plan, le fond du widget. Exemple : bg="#333300"
  • width : la largeur du widget en nombre de caractères si le widget contient du texte, comme ici
  • height : la hauteur du widget. Correspond au nombre de lignes si le widget contient du texte, comme ici
Label texte
Label texte

Voilà le code, dont

  • la création en ligne 11
  • l'affichage dans la fenetre à l'aide de la méthode pack en ligne 12
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
import tkinter as tk # Création de la fenêtre du logiciel fenetre = tk.Tk() # Configuration de la fenêtre fenetre.geometry("600x300") fenetre.title("Ma super application") fenetre.configure(bg="black") # Création-configuration d'un Label et affichage monLabel = tk.Label(fenetre, text = "Bonjour", fg="white", bg="#884400", width=10, height=5) monLabel.pack() # Surveillance des événements fenetre.mainloop()

Modification après création

Pour modifier un widget déjà créé, on peut utiliser la méthode configure qui permet de configurer ou reconfigurer les attributs du widget.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
import tkinter as tk # Création de la fenêtre du logiciel fenetre = tk.Tk() # Configuration de la fenêtre fenetre.geometry("600x300") fenetre.title("Ma super application") fenetre.configure(bg="black") # Création et configuration d'un Label puis affichage monLabel = tk.Label(fenetre, text = "Bonjour", fg="white", bg="#884400", width=10, height=5) monLabel.pack() # Modification du Label monLabel.configure(text="NEW !", fg="black", bg="#BBBBFF") # Surveillance des événements fenetre.mainloop()

La ligne 15 permet de modifier les valeurs choisies au départ. Le carré n'affichage plus le même texte et n'a plus la même couleur.

Label texte modifié
Label texte modifié

Lecture des attributs

Si vous voulez lire et enregistrer la valeur d'un attribut d'un widget, il faut utiliser la méthode cget.

En voici quelques exemples sur les lignes 15 à 17 :

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
import tkinter as tk # Création de la fenêtre du logiciel fenetre = tk.Tk() # Configuration de la fenêtre fenetre.geometry("600x300") fenetre.title("Ma super application") fenetre.configure(bg="black") # Création et configuration d'un Label puis affichage monLabel = tk.Label(fenetre, text = "Bonjour", fg="white", bg="#884400", width=10, height=5) monLabel.pack() # Récupération des valeurs des attributs texte = monLabel.cget("text") ecriture = monLabel.cget("fg") fond = monLabel.cget("bg") largeur = monLabel.cget("width") # Surveillance des événements fenetre.mainloop()

Si on lance l'application, qu'on la ferme et qu'on tente de voir le contenu des variables dans le Shell, on aura ceci :

>>> texte 'Bonjour' >>> ecriture 'white' >>> fond '#884400' >>> largeur 10

3 - Création d'événements à surveiller

Tout d'abord : qu'est-ce qu'un événement pour l'interface ? Il s'agit d'une modification de l'environnement extérieur : une touche de clavier sur laquelle on appuie, le déplacement de la souris, l'appui sur une touche de la souris ...

La traduction d'événement est event.

Lorsqu'on constate un événement / event, encore faut-il le gérer.

C'est le rôle du gestionnaire d'événement, qu'on traduit par event handler. C'est ce gestionnaire qui va donner l'ordre à la fonction désignée de s'activer si tel ou tel événement survient.

Pour créer une liaison événement - action à réaliser, il faut utiliser la méthode bind, appliquée au widget qu'on veut associer à l'événement.

Exemple  Clic-gauche sur le label

Le clic-gauche est identifié par '<Button-1>'. Si veut l'associer au widget monLabel de façon à ce qu'il lance la fonction ca_fonctionne lorsqu'on clique (gauche) sur le widget, il faut mettre ceci dans le code :

monLabel.bind('<Button-1>', ca_fonctionne)

Voici un code-exemple qui modifie l'affichage dans le Label à chaque fois qu'on clique dessus avec le bouton gauche.

Attention, la fonction ca_fonctionne ne peut pas être une fonction comme les autres : elle doit pouvoir recevoir un premier paramètre qui contiendra les données de l'événement. Nous en reparlerons juste après.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
import tkinter as tk # Déclaration des fonctions def ca_fonctionne(event) : lecture = monLabel.cget('text') if lecture == "Bonjour" : monLabel.configure(text="Ca va ?") else : monLabel.configure(text="Bonjour") # Création de la fenêtre du logiciel fenetre = tk.Tk() # Configuration de la fenêtre fenetre.geometry("600x300") fenetre.title("Ma super application") fenetre.configure(bg="black") # Création et configuration d'un Label puis affichage monLabel = tk.Label(fenetre, text = "Bonjour", fg="white", bg="#884400", width=10, height=5) monLabel.pack() # Activation des événements à surveiller monLabel.bind('<Button-1>', ca_fonctionne) # Surveillance des événements fenetre.mainloop()

Variante : les 3 boutons :

  • Le clic-gauche est identifié par '<Button-1>'.
  • Le clic-molette est identifié par '<Button-2>'.
  • Le clic-droit est identifié par '<Button-3>'.

Variante : activation au relachement :

Les événements précédents sont activés dès qu'on appuie. Parfois, il est plus prudent de ne l'activer qu'au relachement. Comment ? En utilisant plutôt ceci :

  • monLabel.bind('<ButtonRelease-1>', ca_fonctionne)
  • monLabel.bind('<ButtonRelease-2>', ca_fonctionne)
  • monLabel.bind('<ButtonRelease-3>', ca_fonctionne)

Objet Event

Le problème de la méthode précédente ? Si on a deux Labels sur lequels on veut faire pareil, on doit créer deux fonctions. On peut faire mieux.

L'objet event contient beaucoup d'informations sur l'événement, dont :

  • L'identifiant-mémoire du widget ayant déclenché l'événement : event.widget
  • La coordonnée locale x de la souris dans le widget au moment de l'événement : event.x
  • La coordonnée locale y de la souris dans le widget au moment de l'événement : event.y
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
import tkinter as tk # Déclaration des fonctions def ca_fonctionne(event) : leLabel = event.widget nouveau_texte = f"x={event.x} y={event.y}" leLabel.configure(text=nouveau_texte) # Création de la fenêtre du logiciel fenetre = tk.Tk() # Configuration de la fenêtre fenetre.geometry("600x300") fenetre.title("Ma super application") fenetre.configure(bg="black") # Création et configuration des Labels puis affichage monLabel1 = tk.Label(fenetre, text = "Label 1 !", fg="white", bg="#884400", width=10, height=5) monLabel2 = tk.Label(fenetre, text = "Label 2 !", fg="white", bg="#448800", width=10, height=5) monLabel1.pack() monLabel2.pack() # Activation des événements à surveiller monLabel1.bind('<Button-1>', ca_fonctionne) monLabel2.bind('<Button-1>', ca_fonctionne) # Surveillance des événements fenetre.mainloop()

Coordonnées sur l'écran

On peut aussi obtenir les coordonnées du clic sur l'écran en lui-même.

Le point (0,0) est alors le coin supérieur gauche de votre écran, plus du widget lui-même.

Il suffit d'évaluer event.x_root et event.y_root.

Conclusion

Voici une liste des événements les plus utiles en lien avec la souris. La dernière colonne correspond au numéro permettant de savoir quel type d'événement a eu lieu avec event.type.

Nom à utiliser dans bind Description Type (event.type)
'<Button-X>' L'utilisateur vient d'appuyer sur l'un des boutons de la souris.
Exemple : <fenetre.bind('<Button-1>', action) pour lier l'action à toute l'application.
4
'<ButtonRelease-1>'L'utilisateur vient de relacher l'un des boutons de la souris.
Exemple : '<ButtonRelease-1>'. A priviligier par rapport au type 4 : l'utilisateur peut sortir du widget pour désactiver son action en cas d'erreur, alors que l'exécution est automatique en cas de type 4 (Button).
5
'<Motion>'L'utilisateur a bougé la souris au dessus du widget.
Exemple : <fenetre.bind('<Motion>', action)
6
'<Enter>'L'utilisateur vient de faire rentrer la souris dans le Widget.
Exemple : <monLabel.bind('<Enter>', action)
L'activation ne se fait que lors de la rentrée.
7
'<Leave>'L'utilisateur vient de faire sortir la souris d'un Widget
Exemple : <monLabel.bind('<Enter>', action)
L'activation ne se fait que lors de la sortie.
8

Il en existe beaucoup d'autres. Allez voir la documentation externe si vous désirez faire quelque chose qui n'est pas réalisable avec ceux-ci.

La fenêtre principale de l'application contient également la méthode bind. Vous pouvez donc l'utiliser pour obtenir la position de la souris sur l'application.

4 - Placement des widgets avec place

Pour l'instant, les widgets se placent les uns sous les autres car on utilise simplement la méthode de placement pack sans lui fournir de paramètres.

On peut faire mieux avec cette méthode mais le but n'est pas de faire de vous des spécialistes de Tkinter.

Dans un premier temps, je parlerai donc simplement de la méthode place qui permet d'afficher les widgets en donnant les coordonnées x et y où on veut voir apparaitre le coin supérieur gauche du widget concerné.

Exemple :

monLabel.place(x=50, y=100)

A titre d'exemple, une application où le Label texte bouge aléatoirement de place à chaque fois qu'on clique dessus.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
import tkinter as tk import random as rd # Déclaration des fonctions def bouge(event) : leLabel = event.widget x = rd.randint(0, XMAX) y = rd.randint(0, YMAX) leLabel.place(x=x, y=y) # Constantes XMAX = 600 YMAX = 300 # Création de la fenêtre du logiciel fenetre = tk.Tk() # Configuration de la fenêtre fenetre.geometry(f"{XMAX}x{YMAX}") fenetre.title("Ma super application") fenetre.configure(bg="black") # Création et configuration des Labels puis affichage monLabel1 = tk.Label(fenetre, text = "Label 1 !", fg="white", bg="#884400", width=10, height=5) monLabel2 = tk.Label(fenetre, text = "Label 2 !", fg="white", bg="#448800", width=10, height=5) monLabel1.place(x=50, y=50) monLabel2.place(x=100, y=100) # Activation des événements à surveiller monLabel1.bind('<Button-1>', bouge) monLabel2.bind('<Button-1>', bouge) # Surveillance des événements fenetre.mainloop()

5 - After

Une dernière chose : la méthode after appliquée à votre application permet de relancer automatiquement la fonction-argument au bout d'un certain temps exprimée en ms.

On reprend l'exemple précédent mais cette fois, les Labels changent de place automatiquement toutes les 0.5 s

Comment ?

  • On crée ligne 35 un tableau qui contient les références des Labels
  • On active ligne 38 une fonction bouge
  • Dans cette fonction (voir lignes 5 à 10) :
    • On récupère avec une boucle for ... in (ligne 6) les références des widgets Labels.
      • On tire aléatoirement deux coordonnées dans la fenêtre (lignes 7-8)
      • On place le widget au nouvel emplacement (ligne 9)
    • On lance l'appel récursif à la même fonction dans 500 ms, soit 0,5 (ligne 10).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
import tkinter as tk import random as rd # Déclaration des fonctions def bouge() : for widget in lesLabels : x = rd.randint(0, XMAX - 80) y = rd.randint(0, YMAX - 80) widget.place(x=x, y=y) fenetre.after(500, bouge) # Constantes XMAX = 600 YMAX = 300 # Création de la fenêtre du logiciel fenetre = tk.Tk() # Configuration de la fenêtre fenetre.geometry(f"{XMAX}x{YMAX}") fenetre.title("Ma super application") fenetre.configure(bg="black") # Création et configuration des Labels puis affichage monLabel1 = tk.Label(fenetre, text = "Label 1 !", fg="white", bg="#884400", width=10, height=5) monLabel2 = tk.Label(fenetre, text = "Label 2 !", fg="white", bg="#448800", width=10, height=5) monLabel3 = tk.Label(fenetre, text = "Label 3 !", fg="white", bg="#008844", width=10, height=5) monLabel4 = tk.Label(fenetre, text = "Label 4 !", fg="white", bg="#004488", width=10, height=5) monLabel1.place(x=50, y=50) monLabel2.place(x=100, y=100) monLabel3.place(x=300, y=100) monLabel4.place(x=200, y=200) # Création de la liste des widgets à gérer lesLabels = [monLabel1, monLabel2, monLabel3, monLabel4] # Activation de la fonction d'animation automatique bouge() # Surveillance des événements fenetre.mainloop()

Dans les prochaines fiches tkinter vous en apprendrez encore un peu plus. D'ici là, n'hésitez pas à poser des questions ou à utiliser un moteur de recherche.

Article publié le 20 11 2019
Dernière modification : 24 11 2019
Auteur : ows. h.