Mis à jour le vendredi 17 novembre 2017
  • 40 heures
  • Difficile

Ce cours est visible gratuitement en ligne.

Ce cours existe en livre papier.

Vous pouvez obtenir un certificat de réussite à l'issue de ce cours.

Vous pouvez être accompagné et mentoré par un professeur particulier par visioconférence sur ce cours.

J'ai tout compris !

Des interfaces graphiques avec Tkinter

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Nous allons maintenant voir comment créer des interfaces graphiques à l'aide d'un module présent par défaut dans Python : Tkinter.

Ce module permet de créer des interfaces graphiques en offrant une passerelle entre Python et la bibliothèque Tk.

Vous allez pouvoir apprendre dans ce chapitre à créer des fenêtres, créer des boutons, faire réagir vos objets graphiques à certains évènements…

Présentation de Tkinter

Tkinter (Tk interface) est un module intégré à la bibliothèque standard de Python, bien qu'il ne soit pas maintenu directement par les développeurs de Python. Il offre un moyen de créer des interfaces graphiques via Python.

Tkinter est disponible sur Windows et la plupart des systèmes Unix. Les interfaces que vous pourrez développer auront donc toutes les chances d'être portables d'un système à l'autre.

Notez qu'il existe d'autres bibliothèques pour créer des interfaces graphiques. Tkinter a l'avantage d'être disponible par défaut, sans nécessiter une installation supplémentaire.

Pour savoir si vous pouvez utiliser le module Tkinter via la version de Python installée sur votre système, tapez dans l'interpréteur en ligne de commande Python :

from tkinter import *

Si une erreur se produit, vous devrez aller vous renseigner sur la page du Wiki Python consacrée à Tkinter.

Votre première interface graphique

Nous allons commencer par voir le code minimal pour créer une fenêtre avec Tkinter. Petit à petit, nous allons apprendre à rajouter des choses, mais commençons par voir la base de code que l'on retrouve d'une interface Tkinter à l'autre.

Étant en Python, ce code minimal est plutôt court :

"""Premier exemple avec Tkinter.

On crée une fenêtre simple qui souhaite la bienvenue à l'utilisateur.

"""

# On importe Tkinter
from tkinter import *

# On crée une fenêtre, racine de notre interface
fenetre = Tk()

# On crée un label (ligne de texte) souhaitant la bienvenue
# Note : le premier paramètre passé au constructeur de Label est notre
# interface racine
champ_label = Label(fenetre, text="Salut les Zér0s !")

# On affiche le label dans la fenêtre
champ_label.pack()

# On démarre la boucle Tkinter qui s'interompt quand on ferme la fenêtre
fenetre.mainloop()

Vous pouvez voir le résultat à la figure suivante.

Notre première fenêtre avec Tkinter

Vous pouvez recopier ce code dans un fichier.py(n'oubliez pas de rajouter la ligne spécifiant l'encodage). Vous pouvez ensuite exécuter votre programme, ce qui affiche une fenêtre (simple, certes, mais une fenêtre tout de même).

Comme vous pouvez le voir, la fenêtre est tout juste assez grande pour que le message s'affiche.

Regardons le code d'un peu plus près.

  1. On commence par importer Tkinter, sans grande surprise.

  2. On crée ensuite un objet de la classeTk. La plupart du temps, cet objet sera la fenêtre principale de notre interface.

  3. On crée unLabel, c'est-à-dire un objet graphique affichant du texte

  4. On appelle la méthodepackde notreLabel. Cette méthode permet de positionner l'objet dans notre fenêtre (et, par conséquent, de l'afficher).

  5. Enfin, on appelle la méthodemainloopde notre fenêtre racine. Cette méthode ne retourne que lorsqu'on ferme la fenêtre.

Quelques petites précisions :

  • Nos objets graphiques (boutons, champs de texte, cases à cocher, barres de progression…) sont appelés des widgets.

  • On peut préciser plusieurs options lors de la construction de nos widgets. Ici, on définit l'optiontextde notreLabelà"Salut les Zér0s !".

Il existe d'autres options communes à la plupart des widgets (la couleur de fondbg, la couleur du widgetfg, etc.) et d'autres plus spécifiques à un certain type de widget. LeLabelpar exemple possède l'optiontextreprésentant le texte affiché par leLabel.

Comme nous l'avons vu, vous pouvez modifier des options lors de la création du widget. Mais vous pouvez aussi en modifier après :

>>> champ_label["text"]
'Salut les Zér0s !'
>>> champ_label["text"] = "Maintenant, au revoir !"
>>> champ_label["text"]
'Maintenant, au revoir !'
>>>

Comme vous le voyez, vous passez entre crochets (comme pour accéder à une valeur d'un dictionnaire) le nom de l'option. C'est le même principe pour accéder à la valeur actuelle de l'option ou pour la modifier.

Nous allons voir quelques autres widgets de Tkinter à présent.

De nombreux widgets

Tkinter définit un grand nombre de widgets pouvant être utilisés dans notre fenêtre. Nous allons en voir ici quelques-uns.

Les widgets les plus communs

Les labels

C'est le premier widget que nous avons vu, hormis notre fenêtre principale qui en est un également. On s'en sert pour afficher du texte dans notre fenêtre, du texte qui ne sera pas modifié par l'utilisateur.

champ_label = Label(fenetre, text="contenu de notre champ label")
champ_label.pack()

N'oubliez pas que, pour qu'un widget apparaisse, il faut :

  • qu'il prenne, en premier paramètre du constructeur, la fenêtre principale ;

  • qu'il fasse appel à la méthodepack.

La méthodepackpermet de positionner un objet dans une fenêtre ou dans un cadre, nous verrons plus loin quelques-uns de ses paramètres optionnels.

Les boutons

Les boutons sont des widgets sur lesquels on peut cliquer et qui peuvent déclencher des actions ou commandes comme nous le verrons ultérieurement plus en détail.

bouton_quitter = Button(fenetre, text="Quitter", command=fenetre.quit)
bouton_quitter.pack()

J'imagine que vous vous posez des questions sur le dernier paramètre passé à notre constructeur deButton. Il s'agit de l'action liée à un clic sur le bouton. Ici, c'est la méthodequitde notre fenêtre racine qui est appelée.

Ainsi, quand vous cliquez sur le boutonQuitter, la fenêtre se ferme. Nous verrons plus tard comment créer nos propres commandes.

Une ligne de saisie

Le widget que nous allons voir à présent est une zone de texte dans lequel l'utilisateur peut écrire. En fait de zone, il s'agit d'une ligne simple.

On préférera créer une variable Tkinter associée au champ de texte. Regardez le code qui suit :

var_texte = StringVar()
ligne_texte = Entry(fenetre, textvariable=var_texte, width=30)
ligne_texte.pack()

À la ligne 1, nous créons une variable Tkinter. En résumé, c'est une variable qui va ici contenir le texte de notreEntry. Il est possible de lier cette variable à une méthode de telle sorte que la méthode soit appelée quand la variable est modifiée (l'utilisateur écrit dans le champEntry).

Pour en savoir plus, je vous renvoie à la méthodetracede la variable.

Comme vous l'avez peut-être remarqué, le widgetEntryn'est qu'une zone de saisie. Pour que l'utilisateur sache ce qu'il doit y écrire, il pourrait être utile de lui mettre une indication auprès du champ. Le widgetLabelest le plus approprié dans ce cas.

Notez qu'il existe également le widgetTextqui représente un champ de texte à plusieurs lignes.

Les cases à cocher

Les cases à cocher sont définies dans la classeCheckbutton. Là encore, on utilise une variable pour surveiller la sélection de la case.

Pour surveiller l'état d'une case à cocher (qui peut être soit active soit inactive), on préférera créer une variable de typeIntVarplutôt queStringVar, bien que ce ne soit pas une obligation.

var_case = IntVar()
case = Checkbutton(fenetre, text="Ne plus poser cette question", variable=var_case)
case.pack()

Vous pouvez ensuite contrôler l'état de la case à cocher en interrogeant la variable :

var_case.get()

Si la case est cochée, la valeur renvoyée par la variable sera1. Si elle n'est pas cochée, ce sera0.

Notez qu'à l'instar d'un bouton, vous pouvez lier la case à cocher à une commande qui sera appelée quand son état change.

Les boutons radio

Les boutons radio (radio buttons en anglais) sont des boutons généralement présentés en groupes. C'est, à proprement parler, un ensemble de cases à cocher mutuellement exclusives : quand vous cliquez sur l'un des boutons, celui-ci se sélectionne et tous les autres boutons du même groupe se désélectionnent.

Ce type de bouton est donc surtout utile dans le cadre d'un regroupement.

Pour créer un groupe de boutons, il faut simplement qu'ils soient tous associés à la même variable (là encore, une variable Tkinter). La variable peut posséder le type que vous voulez.

Quand l'utilisateur change le bouton sélectionné, la valeur de la variable change également en fonction de l'optionvalueassociée au bouton. Voyons un exemple :

var_choix = StringVar()

choix_rouge = Radiobutton(fenetre, text="Rouge", variable=var_choix, value="rouge")
choix_vert = Radiobutton(fenetre, text="Vert", variable=var_choix, value="vert")
choix_bleu = Radiobutton(fenetre, text="Bleu", variable=var_choix, value="bleu")

choix_rouge.pack()
choix_vert.pack()
choix_bleu.pack()

Pour récupérer la valeur associée au bouton actuellement sélectionné, interrogez la variable :

var_choix.get()
Les listes déroulantes

Ce widget permet de construire une liste dans laquelle on peut sélectionner un ou plusieurs éléments. Le fonctionnement n'est pas tout à fait identique aux boutons radio. Ici, la liste comprend plusieurs lignes et non un groupe de boutons.

Créer une liste se fait assez simplement, vous devez commencer à vous habituer à la syntaxe :

liste = Listbox(fenetre)
liste.pack()

On insère ensuite des éléments. La méthodeinsertprend deux paramètres :

  1. la position à laquelle insérer l'élément ;

  2. l'élément même, sous la forme d'une chaîne de caractères.

Si vous voulez insérer des éléments à la fin de la liste, utilisez la constanteENDdéfinie par Tkinter :

liste.insert(END, "Pierre")
liste.insert(END, "Feuille")
liste.insert(END, "Ciseau")

Pour accéder à la sélection, utilisez la méthodecurselectionde la liste. Elle renvoie un tuple de chaînes de caractères, chacune étant la position de l'élément sélectionné.

Par exemple, siliste.curselection()renvoie('2',), c'est le troisième élément de la liste qui est sélectionné (Ciseauen l'occurrence).

Organiser ses widgets dans la fenêtre

Il existe plusieurs widgets qui peuvent contenir d'autres widgets. L'un d'entre eux se nommeFrame. C'est un cadre rectangulaire dans lequel vous pouvez placer vos widgets... ainsi que d'autres objetsFramesi besoin est.

Si vous voulez qu'un widget apparaisse dans un cadre, utilisez leFramecomme parent à la création du widget :

cadre = Frame(fenetre, width=768, height=576, borderwidth=1)
cadre.pack(fill=BOTH)

message = Label(cadre, text="Notre fenêtre")
message.pack(side="top", fill=X)

Comme vous le voyez, nous avons passé plusieurs arguments nommés à notre méthodepack. Cette méthode, je vous l'ai dit, sert à placer nos widgets dans la fenêtre (ici, dans le cadre).

En précisantside="top", on demande à ce que le widget soit placé en haut de son parent (ici, notre cadre).

Il existe aussi l'argument nomméfillqui permet au widget de remplir le widget parent, soit en largeur si la valeur estX, soit en hauteur si la valeur estY, soit en largeur et hauteur si la valeur estBOTH.

D'autres arguments nommés existent, bien entendu. Si vous voulez une liste exhaustive, rendez-vous sur le chapitre consacré à Tkinter dans la documentation officielle de Python.

Une partie est consacrée au packer et à la méthodepack.

Notez qu'il existe aussi le widgetLabelframe, un cadre avec un titre, ce qui nous évite d'avoir à placer unlabelen haut du cadre. Il se construit comme unFramemais peut prendre en argument, à la construction, le texte représentant le titre :cadre = Labelframe(..., text="Titre du cadre")

Bien d'autres widgets

Vous devez vous en douter, ceci n'est qu'une approche très sommaire de quelques widgets de Tkinter. Il en existe de nombreux autres et ceux que nous avons vus ont bien d'autres options.

Il est notamment possible de créer une barre de menus avec ses menus imbriqués, d'afficher des images, des canvas dans lequel vous pouvez dessiner pour personnaliser votre fenêtre... bref, il vous reste bien des choses à voir, même si ce chapitre ne peut pas couvrir tous ces widgets et options.

Je vous propose pour l'heure d'aller jeter un coup d'œil sur les commandes que nous avons effleurées jusqu'ici sans trop nous pencher dessus.

Les commandes

Nous avons vu très brièvement comment faire en sorte qu'un bouton ferme une fenêtre quand on clique dessus :

bouton_quitter = Button(fenetre, text="Quitter", command=fenetre.quit)

C'est le dernier argument qui est important ici. Il a pour nomcommandet a pour valeur la méthodequitde notre fenêtre.

Sur ce modèle, nous pouvons créer assez simplement des commandes personnalisées, en écrivant des méthodes.

Cependant, il y a ici une petite subtilité : la méthode que nous devons créer ne prend aucun paramètre. Si nous voulons qu'un clic sur le bouton modifie le bouton lui-même ou un autre objet, nous devons placer nos widgets dans un corps de classe.

D'ailleurs, à partir du moment où on sort du cadre d'un test, il est préférable de mettre le code dans une classe.

On peut la faire hériter deFrame, ce qui signifie que notre classe sera un widget elle aussi. Voyons un code complet que j'expliquerai plus bas :

from tkinter import *

class Interface(Frame):
    
    """Notre fenêtre principale.
    Tous les widgets sont stockés comme attributs de cette fenêtre."""
    
    def __init__(self, fenetre, **kwargs):
        Frame.__init__(self, fenetre, width=768, height=576, **kwargs)
        self.pack(fill=BOTH)
        self.nb_clic = 0
        
        # Création de nos widgets
        self.message = Label(self, text="Vous n'avez pas cliqué sur le bouton.")
        self.message.pack()
        
        self.bouton_quitter = Button(self, text="Quitter", command=self.quit)
        self.bouton_quitter.pack(side="left")
        
        self.bouton_cliquer = Button(self, text="Cliquez ici", fg="red",
                command=self.cliquer)
        self.bouton_cliquer.pack(side="right")
    
    def cliquer(self):
        """Il y a eu un clic sur le bouton.
        
        On change la valeur du label message."""
        
        self.nb_clic += 1
        self.message["text"] = "Vous avez cliqué {} fois.".format(self.nb_clic)

Et pour créer notre interface :

fenetre = Tk()
interface = Interface(fenetre)

interface.mainloop()
interface.destroy()

La figure suivante vous montre le résultat obtenu.

La fenêtre est créée avec ses deux boutons

Dans l'ordre :

  1. On crée une classe qui contiendra toute la fenêtre. Cette classe hérite deFrame, c'est-à-dire d'un cadre Tkinter.

  2. Dans le constructeur de la fenêtre, on appelle le constructeur du cadre et onpack(positionne et affiche) le cadre.

  3. Toujours dans le constructeur, on crée les différents widgets de la fenêtre. On les positionne et les affiche également.

  4. On crée une méthode  bouton_cliquer, qui est appelée quand on clique sur lebouton_cliquer. Elle ne prend aucun paramètre. Elle va mettre à jour le texte contenu dans le labelself.messagepour afficher le nombre de clics enregistrés sur le bouton.

  5. On crée la fenêtreTkqui est l'objet parent de l'interface que l'on instancie ensuite.

  6. On rentre dans la bouclemainloop. Elle s'interrompra quand on fermera la fenêtre.

  7. Ensuite, on détruit la fenêtre grâce à la méthodedestroy.

Pour conclure

Ceci n'est qu'un survol, j'insiste sur ce point. Tkinter est une bibliothèque trop riche pour être présentée en un chapitre. Vous trouverez de nombreux exemples d'interfaces de par le Web, si vous cherchez quelque chose de plus précis.

En résumé

  • Tkinter est un module intégré à la bibliothèque standard et permettant de créer des interfaces graphiques.

  • Les objets graphiques (boutons, zones de texte, cases à cocher…) sont appelés des widgets.

  • Dans Tkinter, les widgets prennent, lors de leur construction, leur objet parent en premier paramètre.

  • Chaque widget possède des options qu'il peut préciser comme arguments nommés lors de sa construction.

  • On peut également accéder aux options d'un widget ainsi :widget["nom_option"].

Exemple de certificat de réussite
Exemple de certificat de réussite