Python

Tkinter
Exercices pour débuter

Attention ! Les erreurs de programmation avec les interfaces graphiques sont souvent nombreuses. Lorsqu'elles se produisent, il faut redémarrer le shell courant afin d'éviter «d'empiler les erreurs». Avec l'interface IEP de Pyzo, cela se fait en cliquant sur le bouton .

Lancer un dé

Le programme incomplet ci-dessous définit une interface graphique minimaliste contenant une zone de texte et deux boutons [Lancer] et [Quitter]. Seul le bouton [Quitter] est actif.

  1. Le bouton [Lancer] fait appel à la fonction lancer(). Compléter cette fonction pour que la variable resultat prenne pour valeur un entier aléatoire entre 1 et 6.
  2. lancer() doit aussi modifier l'affichage de la zone texte_affiche pour que la valeur de resultat y apparaisse. [Lancer] plusieurs fois le dé pour commencer à «jouer».
                        			
##-----Importation des Modules-----##
from tkinter import *

##-----Définition des Fonctions-----##
def lancer():
    """Cette fonction simule le lancer d'un dé à 6 faces et affiche le résultat obtenu dans la zone de texte."""
    resultat = 0

##-----Création de la fenêtre-----##
fen = Tk()
fen.title('Lancer un dé')

##-----Création des boutons-----##
bouton_lancer = Button(fen, text='Lancer', command=lancer)
bouton_lancer.grid(row = 1, column = 0, padx=5, pady=3)

bouton_quitter = Button(fen, text='Quitter', command=fen.destroy)
bouton_quitter.grid(row = 1, column = 1, padx=5, pady=3)

##-----Création des zones de texte-----##
texte_affiche = Label(fen, text='')
texte_affiche.grid(row = 0, column = 0, columnspan=2)

##-----Programme principal-----##
fen.mainloop()                          # Boucle d'attente des événements
  • Une piste ?
  • Encore ?
  • Une analyse ?
  • Solution
Pour simuler le lancer d'un dé, il faut penser à importer un module supplémentaire.
Pour modifier l'apparence ou le contenu d'un widget, on utilise la méthode .configure.
Pas d'analyse dans cet exercice.
                        	
##-----Importation des Modules-----##
from tkinter import *
from random import *


##-----Définition des Fonctions-----##
def lancer():
    """Cette fonction simule le lancer d'un dé à 6 faces et affiche le résultat obtenu dans la zone de texte."""
    resultat = randint(1, 6)
    texte_affiche.configure(text = str(resultat))


##-----Création de la fenêtre-----##
fen = Tk()
fen.title('Lancer un dé')


##-----Création des boutons-----##
bouton_lancer = Button(fen, text='Lancer', command=lancer)
bouton_lancer.grid(row = 1, column = 0, padx=5, pady=3)

bouton_quitter = Button(fen, text='Quitter', command=fen.destroy)
bouton_quitter.grid(row = 1, column = 1, padx=5, pady=3)


##-----Création des zones de texte-----##
texte_affiche = Label(fen, text='')
texte_affiche.grid(row = 0, column = 0, columnspan=2)


##-----Programme principal-----##
fen.mainloop()                          # Boucle d'attente des événements

Un programme inutile

En prenant exemple sur le programme précédent, écrire un nouveau script qui ouvre une fenêtre graphique.

  1. Cette fenêtre doit comporter une zone de texte et trois boutons [Essayer], [Recommencer] et [Quitter].
  2. Un clic sur [Essayer] affiche «Je ne sers à rien» dans la zone de texte.
  3. Un clic sur [Recommencer] affiche sur le bouton [Essayer] «Moi non plus» au lieu de «Essayer».
  • Fenêtre n°1
  • Fenêtre n°2
  • Fenêtre n°3
  • Solution
La fenêtre au départ :
La fenêtre après l'appui sur [Essayer] :
La fenêtre après l'appui sur [Recommencer] :
                        	
						
##-----Importation des Modules-----##
from tkinter import *


##-----Définition des Fonctions-----##
def tester():
    """Cette fonction affiche du texte dans la zone de texte."""
    texte_affiche.configure(text = 'Je ne sers à rien')


def retester():
    """Cette fonction modifie le texte affiché sur le bouton_1."""
    bouton_1.configure(text = 'Moi non plus')


##-----Création de la fenêtre-----##
fen = Tk()
fen.title('Modifier un bouton')


##-----Création des boutons-----##
bouton_1 = Button(fen, text='Essayer', command=tester)
bouton_1.grid(row = 1, column = 0, padx=5, pady=3)

bouton_2 = Button(fen, text='Recommencer', command=retester)
bouton_2.grid(row = 1, column = 1, padx=5, pady=3)

bouton_quitter = Button(fen, text='Quitter', command=fen.destroy)
bouton_quitter.grid(row = 1, column = 2, padx=5, pady=3)


##-----Création des zones de texte-----##
texte_affiche = Label(fen, text='')
texte_affiche.grid(row = 0, column = 0, columnspan=3)


##-----Programme principal-----##
fen.mainloop()                          # Boucle d'attente des événements

Formulaire de saisie

Le but de cet exercice est de concevoir la fenêtre ci-contre. L'utilisateur est invité à entrer son prénom. Une fois le bouton [Valider] enclenché, s'affiche le message « Bonjour ... » où les pointillés ... sont remplacés par le prénom saisi.

Cette fenêtre doit comporter une zone de texte, une zone formulaire, une zone de texte pour l'affichage et 2 boutons [Valider] et [Quitter].

  • Une piste
  • Un schéma
  • Une analyse
  • Solution
Dans un premier temps, on pourra concevoir notre grille en se rappelant que l'on peut fusionner des cellules avec rowspan ou columspan.
Et avec ce tableau qui pourrait faire office de grille pour votre fenêtre ?
Le bouton [Valider] lance la fonction prenom() qui va aller lire la variable du formulaire. On peut, pour cela, utiliser la méthode .get() appliquée au formulaire.
                        	
##-----Importation des Modules-----##
from tkinter import *

##----- Définitions des Fonctions -----##
def prenom():
	"""insere le prenom de l'utilisateur dans une zone de texte"""
	var_prenom = form_texte.get()
	texte_reponse.configure(text='Bonjour {}'.format(var_prenom))

##----- Création de la fenêtre -----##
fenetre = Tk()
fenetre.title('Fenêtre de saisie')

##----- Création des boutons -----##
bouton_valider = Button(fenetre,text='Valider', command=prenom)
bouton_valider.grid(row = 2,column = 0, padx = 10, pady = 5)
bouton_quitter = Button(fenetre,text='Quitter', command=fenetre.quit)
bouton_quitter.grid(row = 2,column = 1, padx = 10,pady = 5)

##---- Création des zones de texte -----##
texte_question = Label(fenetre, text='Entrez votre prénom puis valider :')
texte_question.grid(row = 0, column = 0, padx = 10, pady = 5)
texte_reponse = Label(fenetre, text='...')
texte_reponse.grid(row = 1, column = 0, columnspan = 2, padx = 10,pady = 5)

##----- Création des formulaires -----##
form_texte = Entry(fenetre, textvariable=StringVar())
form_texte.grid(row = 0, column = 1, padx = 10,pady = 5)

##----- Programme principal -----##
fenetre.mainloop()

Une liste de carrés et au final un damier !

Le quadrillage ci-contre rentre parfaitement dans le canevas.
Pour cela, on a défini comme variables la longueur c d'un côté d'une case et le nombre n de cases par ligne et par colonne.

A partir du code incomplet ci-dessous,

  1. Complétez les valeurs des paramètres width et height du canevas dessin à la ligne 18.
  2. Le canevas ne se distingue pas du fond de la fenêtre. Changez sa couleur de fond lors de la création du canevas dessin.
  3. Encadrer le canevas par un rectangle noir d'épaisseur de côté 1 et de mêmes dimensions que le canevas. Les coordonnées (x0 ; y0) seront (0 ; 0). Que constate-t-on ? Modifier les coordonnées (x0 ; y0) et (x1 ; y1) de sorte que le rectangle «colle» parfaitement au contour du canevas.
  4. Tracer le carré correspondant à la 3ème colonne et 2ème ligne. On utilisera pour cela les variables n et c.
  5. Déduire de la ligne précédente, une boucle permettant de tracer tous les carrés, appliquez-la pour visualiser le résultat.
  6. Les carrés constituant les cases sont stockés dans une liste de listes, cela nous permettra une réutilisation ultérieure. Complétez ce code afin de générer vos cases :
    for ligne in range(n):          # Les cases de chaque ligne seront stockées dans "transit"
        transit=[]
        for colonne in range(n):    # Conception des cases d'une ligne
            transit.append(dessin.create_rectangle( ,  ,  ,  ))
        cases.append(transit)       # Ajout de la ligne à la liste principale
     
  7. Une fois le quadrillage parfaitement réalisé, utilisez convenablement la méthode .itemconfigure() afin d'obtenir un damier alternant les cases noires et les cases blanches. Le point de réflexion se fera sur le calcul de la somme ligne + colonne.
                        	
##----- Importation des Modules -----##
from tkinter import *

##----- Variables globales -----##
c = 30                          # Longueur d'un côté d'une case
n = 8                           # Nombre de cases par ligne et par colonne
cases = []                      # Liste contenant les objets cases

##----- Création de la fenêtre -----##
fen = Tk()
fen.title('Damier')

##----- Création des boutons -----##
bouton_quitter = Button(fen, text='Quitter', command=fen.quit)
bouton_quitter.grid(row = 1, column = 1, sticky=W+E, padx=3, pady=3)

##----- Création des canevas -----##
dessin = Canvas(fen, width=..., height=...)
dessin.grid(row = 0, column = 0, columnspan=2, padx=3, pady=3)

##----- Programme principal -----##
fen.mainloop()                  # Boucle d'attente des événements
  • Étape n°2
  • Étape n°4
  • Fenêtre
  • Étape n°7
                        	
##----- Importation des Modules -----##
from tkinter import *

##----- Variables globales -----##
c = 30                          # Longueur d'un côté d'une case
n = 8                           # Nombre de cases par ligne et par colonne
cases = []                      # Liste contenant les objets cases

##----- Création de la fenêtre -----##
fen = Tk()
fen.title('Damier')

##----- Création des boutons -----##
bouton_quitter = Button(fen, text='Quitter', command=fen.quit)
bouton_quitter.grid(row = 1, column = 1, sticky=W+E, padx=3, pady=3)

##----- Création des canevas -----##
dessin = Canvas(fen, width=n*c, height=n*c, bg='white')
dessin.grid(row = 0, column = 0, columnspan=2, padx=3, pady=3)

##----- Programme principal -----##
fen.mainloop()                  # Boucle d'attente des événements
                        							
##----- Importation des Modules -----##
from tkinter import *

##----- Variables globales -----##
c = 30                          # Longueur d'un côté d'une case
n = 8                           # Nombre de cases par ligne et par colonne
cases = []                      # Liste contenant les objets cases

##----- Création de la fenêtre -----##
fen = Tk()
fen.title('Damier')

##----- Création des boutons -----##
bouton_quitter = Button(fen, text='Quitter', command=fen.quit)
bouton_quitter.grid(row = 1, column = 1, sticky=W+E, padx=3, pady=3)

##----- Création des canevas -----##
dessin = Canvas(fen, width=n*c, height=n*c, bg='white')
dessin.grid(row = 0, column = 0, columnspan=2, padx=3, pady=3)

##----- Création des figures -----##
cadre = dessin.create_rectangle(1, 1 , n*c, n*c)

dessin.create_rectangle(2*c+1, 1*c+1, 3*c+1, 2*c+1)

##----- Programme principal -----##
fen.mainloop()                  # Boucle d'attente des événements
                        	
##----- Importation des Modules -----##
from tkinter import *

##----- Variables globales -----##
c = 30                          # Longueur d'un côté d'une case
n = 8                           # Nombre de cases par ligne et par colonne
cases = []                      # Liste contenant les objets cases

##----- Création de la fenêtre -----##
fen = Tk()
fen.title('Damier')

##----- Création des boutons -----##
bouton_quitter = Button(fen, text='Quitter', command=fen.quit)
bouton_quitter.grid(row = 1, column = 1, sticky=W+E, padx=3, pady=3)

##----- Création des canevas -----##
dessin = Canvas(fen, width=n*c, height=n*c, bg='white')
dessin.grid(row = 0, column = 0, columnspan=2, padx=3, pady=3)

##----- Création des figures -----##
for ligne in range(n):
	transit=[]
	for colonne in range(n):
		transit.append(dessin.create_rectangle(colonne*c+1, ligne*c+1, (colonne+1)*c+1, (ligne+1)*c+1))
	cases.append(transit)

##----- Modification des figures créées -----##
for ligne in range(n):
    for colonne in range(n):
        if (ligne+colonne)%2 == 0:      # Parité
            dessin.itemconfigure(cases[ligne][colonne], outline='black', fill='black')
        else:
            dessin.itemconfigure(cases[ligne][colonne], outline='white')

##----- Programme principal -----##
fen.mainloop()                  # Boucle d'attente des événements

Les boutons aux commandes

On a programmé ci-dessous une fenêtre contenant un canevas et quatre boutons :

  • le bouton [Tracer un cercle] doit afficher, dans le canevas, un cercle, d'épaisseur 2 pixels, dont les coordonnées (entre 50 et 250) du centre et le rayon (entre 10 et 40) sont aléatoires ;
  • le bouton [Changer de couleur] doit modifier aléatoirement la couleur des tracés suivants. . Les différentes couleurs possibles sont définies dans la liste : ['purple', 'cyan', 'green', 'red', 'blue', 'orange', 'black'] ;
  • le bouton [Effacer] doit effacer tous les cercles déjà tracés. Il doit ré-initialiser la couleur du tracé suivant à 'blue'.

Complétez la définition des fonctions pilotées par ces boutons pour que le programme «fonctionne» correctement.

                        
##----- Importation des Modules -----##
from tkinter import *

##----- Variables globales -----##
couleur = 'blue'                      	# Couleur par défaut

##-----Définition des fonctions-----##
def tracer():
    """Trace un cercle de couleur, de centre un point de coordonnées aléatoires
    (entre 50 et 250) et de rayon aléatoire (entre 10 et 40).."""
    global couleur              		# Variable globale, modifiée dans le programme principal


def change_couleur():
    """Permet le changement aleatoire de couleur parmi les 7 d'une liste donnée."""
    global couleur              		# Variable globale, modifiée dans le programme principal


def effacer():
    """Efface toutes les figures déjà tracée dans le canevas."""
    global couleur


##----- Création de la fenêtre -----##
fen = Tk()
fen.title('Cercles')


##----- Création des boutons -----##
bouton_quitter = Button(fen, text='Quitter', command=fen.quit)
bouton_quitter.grid(row = 1, column = 3, padx=3, pady=3)

bouton_tracer = Button(fen, text='Tracer un cercle', command=tracer)
bouton_tracer.grid(row = 1, column = 0, padx=3, pady=3)

bouton_changer = Button(fen, text='Nouvelle couleur', command=change_couleur)
bouton_changer.grid(row = 1, column = 1, padx=3, pady=3)

bouton_effacer = Button(fen, text='Effacer', command=effacer)
bouton_effacer.grid(row = 1, column = 2, padx=3, pady=3)


##----- Création des canevas -----##
dessin = Canvas(fen, width=302, height=302, bg='white')
dessin.grid(row = 0, column = 0, columnspan=4, padx=3, pady=3)


##----- Programme principal -----##
fen.mainloop()                  # Boucle d'attente des événements
  • Fonction n°1
  • Fonction n°2
  • Fonction n°3
  • Solution
Il ne faut pas oublier d'importer le module random !!!
                        						
    def tracer():
    """Trace un cercle de couleur, de centre un point de coordonnées aléatoires
    (entre 50 et 250) et de rayon aléatoire (entre 10 et 40)."""
    global couleur              		# Variable globale, modifiée dans le programme principal
    x0, y0 = randint(50,250), randint(50,250)
    r = randint(10,40)
    dessin.create_oval(x0-r, y0-r, x0+r, y0+r, width=2, outline=couleur)
                        	
                        def change_couleur():
    """Permet le changement aleatoire de couleur parmi les 7 d'une liste donnée."""
    global couleur              		# Variable globale, modifiée dans le programme principal
    couleur=choice(['purple', 'cyan', 'green', 'red', 'blue', 'orange', 'black'])
                        	
    def effacer():
    """Efface toutes les figures déjà tracée dans le canevas."""
    global couleur
    dessin.delete(ALL)
    couleur='blue'
                        	
                            
##----- Importation des Modules -----##
from tkinter import *
from random import *

##----- Variables globales -----##
couleur = 'blue'                      	# Couleur par défaut

##-----Définition des fonctions-----##
def tracer():
    """Trace un cercle de couleur, de centre un point de coordonnées aléatoires
    (entre 50 et 250) et de rayon aléatoire (entre 10 et 40)."""
    global couleur              		# Variable globale, modifiée dans le programme principal
    x0, y0 = randint(50,250), randint(50,250)
    r = randint(10,40)
    dessin.create_oval(x0-r, y0-r, x0+r+1, y0+r+1, width=2, outline=couleur)


def change_couleur():
    """Permet le changement aleatoire de couleur parmi les 7 d'une liste donnée."""
    global couleur              		# Variable globale, modifiée dans le programme principal
    couleur=choice(['purple', 'cyan', 'green', 'red', 'blue', 'orange', 'black'])


def effacer():
    """Efface toutes les figures déjà tracée dans le canevas."""
    global couleur
    dessin.delete(ALL)
    couleur='blue'


##----- Création de la fenêtre -----##
fen = Tk()
fen.title('Cercles')


##----- Création des boutons -----##
bouton_quitter = Button(fen, text='Quitter', command=fen.quit)
bouton_quitter.grid(row = 1, column = 3, padx=3, pady=3)

bouton_tracer = Button(fen, text='Tracer un cercle', command=tracer)
bouton_tracer.grid(row = 1, column = 0, padx=3, pady=3)

bouton_changer = Button(fen, text='Nouvelle couleur', command=change_couleur)
bouton_changer.grid(row = 1, column = 1, padx=3, pady=3)

bouton_effacer = Button(fen, text='Effacer', command=effacer)
bouton_effacer.grid(row = 1, column = 2, padx=3, pady=3)


##----- Création des canevas -----##
dessin = Canvas(fen, width=302, height=302, bg='white')
dessin.grid(row = 0, column = 0, columnspan=4, padx=3, pady=3)


##----- Programme principal -----##
fen.mainloop()                  # Boucle d'attente des événements