Tkinter (pour Tool kit interface) est une boîte à outils d'interface graphique pour Python. Le module Tkinter s'installe avec Python et est présent par défaut.
Il suffit donc d'importer le module au début d'un script.
L'utilisation d'une bibliothèque comme Tkinter fait partie de ce que l'on appelle la programmation évènementielle : contrairement aux scripts que vous avez écrits jusqu'ici, où les instructions "s'enchaînaient" les unes à la suite des autres dans l'ordre où elles sont écrites, le code va maintenant attendre et ne s’exécuter que si certains évènements se produisent : clic sur un bouton, sur un bouton radio, sélection d'un élément dans une liste, etc...c'est exactement le même concept que l'utilisation de JavaScript et des formulaires pour gérer l'interaction Homme-Machine sur le web !
Pour certains éléments des interfaces graphiques que vous allez construire ( comme les boutons par exemple ), il faudra donc écrire dans le script leur gestionnaire d'évènement, c'est à dire les instructions qui devront être éxécutées lorsqu'un évènement associé à cet élément se produira. Ces gestionnaires d'évènements seront très souvent des fonctions, que l'on appelle dans ce cas fonctions de rappel ( callback ).
Le module Tkinter ne fonctionne pas en ligne; tout le travail de ce chapitre devra donc être fait avec Pyzo.
Les instructions pour la création d'une fenêtre Tkinter "nue" sont les suivantes :
from tkinter import *
fenetre = Tk()
fenetre.title('Fenêtre sur cours ( de Python )')
fenetre.mainloop()
fenetre
" !tk
")Commencer à écrire le script précédent pour vous familiariser avec ces notions de base.
Une fois la fenêtre créée, on peut la "peupler" avec des éléments que l'on appelle widgets, contraction de l'anglais windows gadget ("gadget de fenêtre").
"Widget" est le terme général utilisé pour désigner tous les objets graphiques que l'on peut insérer dans une interface (fenêtre).
Les widgets situés à l'intérieur d'une fenêtre sont les enfants de celle-ci; inversement, la fenêtre est la parente des widgets.
De nombreux widgets existent, parmi lesquels par exemple :
Button
( bouton pour commander une action)Label
( étiquette pour insérer un texte)Entry
( champ de saisie utilisateur pour permettre l'entrée d'une donnée)Chaque widget a des propriétés et des fonctions qui permettent de régler son apparence et les interactions avec l'utilisateur.
Chaque widget (objet d'interface) doit d'abord être créé en mémoire, puis placé ( = affiché ) dans la fenêtre.
nom = Button(parent, text = "texte à afficher dans le bouton", command = rappel )
text
indique le texte qui doit être affiché sur le bouton.command
permet d'indiquer le nom ( sans guillemets et sans parenthèses ) de la fonction de rappel qui sera appelée automatiquement lorsque l'évènement "clic sur le bouton" se produira.
bouton = Button( fenetre , text = "Quitter", command = fenetre.destroy) # Création du bouton
bouton.pack() # Affichage du bouton dans la fenêtre
.pack()
).La fonction de rappel peut être choisie parmi les fonctions intégrées au système, ou celles définies dans le programme ( lancer d'un calcul, affichage d'une image,...)
Ici, la commande système fenetre.destroy()
est une fonction qui "détruit" l'objet nommé fenetre en mémoire. La pression du bouton a donc ici pour conséquence
la fermeture de la fenêtre nommée fenetre.
# gestionnaire d'évènements du bouton ( fonction de rappel )
def afficher():
........
........
# construction de l'interface
......
bouton = Button( fenetre , text = "Afficher", command = afficher)
bouton.pack()
......
On notera qu'il est impossible de passer des arguments à une fonction de rappel ( elle ne prend donc aucun paramètre ).
Cela peut parfois poser des problèmes, mais il existe des moyens de les contourner.
nom = Label(parent, text = 'texte à afficher', fg = 'couleur du texte', bg = 'couleur du fond' )
texte = Label( Fenetre, text = "Hello World", fg = 'black', bg = 'white') # Création d'un label avec un texte noir sur fond blanc
texte.pack() # Insertion du label dans la fenêtre
Les couleurs du label ( fg
= foreground = premier plan ) et de fond ( bg
= background = arrière-plan ) sont à indiquer en anglais !
D'autres propriétés existent, et sont également modifiables ( police du texte, taille des caractères,...)
nom = Entry( parent )
entree = Entry( fenetre ) # Création d'un champ de saisie nommé Entree
entree.pack()# insertion du champ dans la fenêtre "fenetre"
L'instruction pack()
utilisée précédemment sans précision place par défaut les widgets les uns en dessous des autres dans la fenêtre; il existe bien entendu une manière plus "fine" de gérer ce positionnement.
Tkinter dispose en fait de plusieurs gestionnaires de placement pour les widgets :
pack()
déjà vu précédemment : souvent difficile à maîtriser car pas très intuitif...grid()
: beaucoup plus simple à manipuler, puisqu'il suffit de voir la fenêtre comme une grille, dans laquelle on positionne les widgets en indiquant à quelle ligne ( row )
et à quelle colonne ( column ) il doit se positionner.Exemple :
# création des widgets
bouton1 = Button(ma_fenetre, text = "Bouton 1")
bouton2 = Button(ma_fenetre, text = "Bouton 2")
etiq = Label(ma_fenetre, text = "Etiquette")
# positionnement des widgets
bouton1.grid(row = 0, column = 2 )
bouton2.grid(row = 2, column = 1 )
etiq.grid(row = 1, column = 0)
Il existe de très nombreux widgets, chacun ayant un certain nombre d'options; impossible de tous les documenter ici. Il faudra donc souvent que vous fassiez vos propres recherches d'informations pour utiliser telle ou telle notion liée à Tkinter...
Vous allez réaliser une interface graphique assez ( très ! ) simple ayant l'aspect ci-dessous :
Quelques indications
Comme dans toute écriture d'un programme avec interface graphique, séparez bien le travail en deux parties :
Pour changer le texte d'une étiquette, mais également pour récupérer le texte rentré par un utilisateur dans un champ de saisie, il faut utiliser avec Tkinter une variable de contrôle; il s'agit d'une variable qui peut être "liée" à un ( ou plusieurs ) widget(s), et qui peut être lue ou modifiée : la modification se "propagera" alors dans tous les widgets au(x)quel(s) est est liée. ( plus de détails ici ).
Pour créer une variable de contrôle :
score = IntVar() # variable de contrôle contenant des valeurs numériques entières
fraction = DoubleVar() # variable de contrôle de type flottant
mot = StringVar() # variable de contrôle contenant des chaînes de caractère
Pour "lier" ensuite la variable de contrôle à un widget, il faut utiliser la propriété textvariable
du widget; par exemple :
label_score = Label ( fen , textvariable = score ) # association de la variable de contrôle "score" à l'étiquette "label_score"
Enfin, pour lire ou pour modifier une variable de contrôle, on utlilise les fonctions get()
( lire ) et set()
( modifier ) :
sc = score.get() # permet de lire le contenu de la variable de contrôle et le placer dans une variable "normale" ( ici "sc" )
mot.set('bla bla bla') # permet de modifier le contenu de la variable de contrôle ( ici avec le texte "bla bla bla" )
Vous vous souvenez de ce jeu ?
L'objectif va être d'écrire une interface graphique pour ce jeu; elle devra comporter ( au moins ) :
Vous pourrez dans un deuxième temps rajouter des widgets, comme par exemple une étiquette pour afficher un score, ou un autre bouton pour relancer le jeu.
Quelques indications :
while
qui "tourne" tant que l'utilisateur n'a pas trouvé le bon nombre; cette boucle sera ici remplacée par la boucle infinie ( mainloop ) de la fenêtre
Tkinter.( Une petite remarque à propos de la variable qui contient le nombre à deviner : étant définie hors de toute fonction, elle sera donc "lisible", depuis la fonction gestionnaire d'évènement; par contre, le gestionnaire d'évènement ne pourra pas la modifier, ce qui n'est de toute façon pas nécessaire...Revoir au besoin le chapitre sur les fonctions pour ces questions de variables locales et globales. )