Connexion élèves

Choisir le(s) module(s) à installer :

Interfaces graphiques en Python avec Tkinter

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.

Principes

Créer une fenêtre pour une application

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()
					
  • Ligne 2 : instruction d'importation de la bibliothèque à placer en début de script; on peut "cibler" cette importation aux uniques éléments nécessaires à l'application : voir ci-dessous pour ces éléments.
  • Ligne 4 : instruction de création en mémoire de la fenêtre ; on peut bien sur utiliser le nom que l'on veut à la place de "fenetre" !
  • Ligne 5 : donne un titre à la fenêtre (par défaut c'est "tk")
  • Ligne 7 : lance la boucle infinie principale : le programme tournera «  en boucle » sans rien faire en attendant des actions de la part de l’utilisateur, actions qui déclencheront alors l’exécution du gestionnaire d'évènement associé à l'élément sur lequel l’utilisateur a agi.
    A placer à la toute fin de la création de l'interface.

Travail à faire

Commencer à écrire le script précédent pour vous familiariser avec ces notions de base.

Les widgets

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 :

  • Les boutons : Button ( bouton pour commander une action)
  • Les labels : Label ( étiquette pour insérer un texte)
  • Les zones de saisie : Entry ( champ de saisie utilisateur pour permettre l'entrée d'une donnée)
  • ...et beaucoup d'autres...

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.

Le widget Button

Syntaxe


nom = Button(parent, text = "texte à afficher dans le bouton", command = rappel )
			

Exemple


bouton = Button( fenetre , text = "Quitter", command = fenetre.destroy)  # Création du bouton
bouton.pack() 	# Affichage du bouton dans la fenêtre
			
On remarque donc que la création d'un widget se fait bien en deux temps :
  1. création en mémoire ( première instruction )
  2. puis affichage ( instruction .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.

Le widget Label

Syntaxe


nom = Label(parent, text = 'texte à afficher', fg = 'couleur du texte', bg = 'couleur du fond' )
			

Exemple


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,...)

Le widget Entry

Syntaxe


nom = Entry( parent )
			

Exemple


entree = Entry( fenetre )  # Création d'un champ de saisie nommé Entree
entree.pack()# insertion du champ dans la fenêtre "fenetre"
			

Positionnement des widgets dans la fenêtre

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 :

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)	
					

Pour aller plus loin...

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...

Mes premières interfaces...

Surtout ne pas appuyer...

Vous allez réaliser une interface graphique assez ( très ! ) simple ayant l'aspect ci-dessous :

Avant l'appui sur le bouton...
Après l'appui
  • l'interface ne contient qu'un seul bouton et deux étiquettes.
  • une des étiquettes est placée juste à droite du bouton, et ne contient aucun texte au démarrage du programme; si l'utilisateur clique sur le bouton ( ce qu'il ne devrait bien sur normalement pas faire...), le texte des étiquettes doit changer...

Quelques indications

Comme dans toute écriture d'un programme avec interface graphique, séparez bien le travail en deux parties :

  • la construction de l'interface elle-même
  • l'écriture des gestionnaires d'évènements et de la logique du programme

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" )				
	 		

Lien vers la RÉPONSE

Le nombre à deviner

Vous vous souvenez de ce jeu ?

L'objectif va être d'écrire une interface graphique pour ce jeu; elle devra comporter ( au moins ) :

  • un champ d'entrée pour que l'utilisateur rentre ses propositions
  • un bouton pour qu'il valide sa proposition
  • une étiquette qui affiche si le nombre est trop petit ou trop grand, ou que l'utilisateur a trouvé le nombre

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 :

  • tel que vous l'aviez écrit, le script contient une boucle 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.
  • le seul évènement à gérer sera le clic sur le bouton : son gestionnaire devra donc évaluer la proposition du joueur, et afficher la situation de cette proposition par rapport au nombre à trouver ( plus grand, plus petit ).
  • le nombre à deviner, tiré au hasard, devra bien être défini en dehors du gestionnaire d'évènement !

( 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. )

Lien vers la RÉPONSE