Sortir de la console¶
Nous avons vu comment construire une interface graphique donnant les différentes combinaisons possibles des composantes RGB. Le travail suivant permet en autonomie la création puis la gestion d’interfaces graphiques (fenêtre, boutons, labels,...) qui donne une véritable Interface Homme-Machine (IHM).
Nous allons ainsi créer une interface qui permet de construire des cercles et des carrés de différentes couleurs dans une zone de dessin. Dans une seconde partie nous créerons des animations pour dynamiser tout cela.
Tout cela dans un seul objectif: créer des jeux!
Notre interface graphique¶
Analyse de notre interface¶

Exemple d'interface graphique
Dans cette interface vous trouverez:
- une zone de commandes contenant les diverses commandes (boutons, échelles, entrée,...)
- une zone de dessin, le canvas.
Achevée, elle permettra de construire des cercles ou des carrés dans le canvas, définis dans leur forme et couleur par les valeurs des différents boutons de commandes...
Vous trouverez ci-dessous, une partie du code qui permet sa construction et que vous devrez compléter tout au long de ce travail:
Code à copier
from tkinter import *
from random import randint
#--------------------- ZONE FONCTIONS -------------------------------------#
#--------------------------------------------------------------------------------#
# CONSTRUCTION DES OBJETS DANS LA FENETRE #
#--------------------------------------------------------------------------------#
fen = Tk()
fen.title( "Les objets graphiques")
fen.geometry('1000x600+100+100')
fen.resizable(False, False)
#widthxheight+bordecran
#--------------------------------------------------------------------------------#
ZoneDessin = Frame(fen, borderwidth = 2, relief = RIDGE)
ZoneDessin.grid(row = 0, column = 0)
#--------------------------------------------------------------------------------#
Can = Canvas(ZoneDessin, bg = 'grey', width = 800, height = 580)
Can.grid()
#--------------------------------------------------------------------------------#
ZoneOptions = LabelFrame(fen, borderwidth = 2, text = 'Options', labelanchor = 'n',
relief = RIDGE,
width = 200, height = 580)
ZoneOptions.grid(row = 0, column = 1)
ZoneOptions.grid_propagate(0)
#--------------------------------------------------------------------------------#
BouDebut = Button (ZoneOptions, text = 'Construire', command = fen.destroy)
BouDebut.grid(row = 0, pady = 20,columnspan = 2)
#--------------------------------------------------------------------------------#
EchelleRayon = Scale(ZoneOptions, orient = 'horizontal', from_=0,
to = 100, resolution = 1, tickinterval = 10, length = 190,
label = 'Dimension du cercle ou du carre')
EchelleRayon.grid(row = 1,columnspan = 2)
#---------------------------------------------------------------------------------#
# INSERER DESSOUS LES AUTRES CONSTRUCTEURS #
#---------------------------------------------------------------------------------#
#---------- NE RIEN METTRE EN DESSOUS DE CETTE LIGNE -----------------------#
fen.mainloop()
Exo
Copier ce code et enregistrez-le dans un nouveau fichier que vous nommerez interface_graphique.py
Analyse du code¶
Pour construire une interface graphique, on fait appel à des constructeurs: Frame, Scale, Button
en sont des exemples. Chaque constructeur est défini dans un élément parent et possède des attributs obligatoires ou optionnels qui lui sont propres.
Info
Le premier constructeur appelé est Tk()
qui construit la fenêtre, appelée fen
ici. Ce constructeur possède les attributs title, geometry
ou encore resizable
et sûrement bien d'autres.
Remarquez que le constructeur Scale
pour faire des curseurs contient beaucoup plus d'attributs...
En résumé...
Et si vous voulez connaître tous les attributs du constructeur Button
, il suffit de se documenter:

Pour se documenter
Vous trouverez ici ou là de quoi vous documentez sur les différents widgets que vous pouvez utiliser.
Le gestionnaire de positionnement¶
Il ne suffit pas de créer les éléments graphiques ; il faut aussi les placer dans leur conteneur. D’ailleurs, les différents widgets n’apparaîtront pas s’ils ne sont pas placés !
Il existe plusieurs façons de positionner des objets mais nous n'utiliserons que le gestionnaire grid
, qui permet de placer les objets dans une grille virtuelle, préalablement réfléchie...
Positionnement relatif
Les objets (widgets) sont positionnés dans leur parent respectif et direct. Le canvas Can
est positionné dans la ZoneDessin
et le bouton Boudebut
dans la ZoneOptions
!
Il est donc important de bien concevoir son projet avant de le réaliser!
Enrichissons notre interface!¶
Nous allons compléter le code proposé ci-dessus afin d'enrichir l'interface par d'autres widgets et voir comment on peut dessiner dans le canvas (zone dédié au dessin...).
Commande pour dessiner dans le canvas...¶
Un canvas est une zone destinée à contenir des dessins ou autres figures complexes (et même des
images...). Par exemple pour créer un cercle rouge dans le canvas Can
, il faut utiliser le constructeur :
x = 400
y = 300
r = 50
Can.create_oval(x - r, y - r, x + r, y + r, fill = 'red')
Exo
- Insérer ce code dans la zone d'insertion et vous devriez voir apparaître un cercle rouge dans le canvas.
- Créer un autre cercle de couleur verte dont les coordonnées du centre sont
225
et458
de rayon200
Pour dessiner un rectangle rose de largeur l
, de hauteur h
centré au point de coordonnées (x,y)
, il suffit d'utiliser le constructeur:
Can.create_rectangle(x - l/2, y - h/2, x + l/2, y + h/2, fill = 'pink')
Exo
Créer dans le canvas, un rectangle bleu centré en (500, 140)
de largeur 100
et de hauteur 60
. N'oubliez pas de créer les variables x, y
et l,h
!
Il existe d'autres constructeurs pour insérer du texte par exemple (create_text()
) ou des polygones plus complexes (create_polygon()
) mais intéressons nous à la façon d'intégrer une image!
Exo
- Récupérer l'image
pacman.png
(ici). - Supprimer les cercles et les rectangles puis insérer le code suivant pour afficher l'image au milieu du canvas:
🐍 Script Python
img = PhotoImage(file = "pacman.png") Can.create_image(400, 290, image = img)
Associer la valeur des widgets à la construction d'une figure élémentaire...¶
Dans cette partie, on souhaite construire des cercles ou des rectangles dont les dimensions sont données par la valeur des quelques widgets présents...
Par exemple, récupérer la valeur donnée par le curseur et construire le cercle dont le rayon est cette valeur. On utilise pour cela une variable de contrôle.
Info
Une variable de contrôle est une variable gobale associée à un widget et sa valeur peut être récupérée partout dans le programme.
Le code suivant permet de définir une variable de contrôle de type Int
.
Exo
- Ajouter le code suivant juste avant le constructeur
EchelleRayon
:🐍 Script Pythonvaleur_curseur = IntVar(ZoneOptions) valeur_curseur.set(5)
- Ajouter au constructeur
EchelleRayon
l'attributvariable = valeur_curseur
.
Nous allons maintenant associer au bouton la commande qui permet de dessiner un cercle dans le canvas. Pour cela, nous allons définir la fonction cercle
qui sera appelée à l'appui sur le bouton.
Exo
- Ajouter dans la zone dédiée aux fonctions, le code suivant:
🐍 Script Python
def cercle(): x, y = randint(0,800),randint(0,580) r = valeur_curseur.get()#permet de récupérer la valeur de la variable valeur_curseur et la stocker dans la variable r Can.create_oval(x - r, y - r, x + r, y + r, fill = 'red')
- Changer l'attibut
command
du bouton, en lui attibuant la valeurcercle
. - Modifier la valeur du curseur et tester la construction pour constater que le rayon du cercle change.
Nous allons maintenant créer de nouveaux widgets pour :
- choisir la couleur(menu déroulant dont le constructuer se nomme
OptionMenu
) - choisir la forme(menu déroulant dont le constructeur se nomme
OptionMenu
) - saisir la valeur du côté du carré (zone de saisir dont le constructeur se nomme
Entry
) - donner des indications (texte dont le constructeur se nomme
Label
)
Exo
Réaliser la construction des widgets ci-dessus ainsi que les variables de contrôles nécessaires. Je rappelle le lien vers l'aide (voir ici)
Et la souris mainenant!¶
Nouvel objectif: dessiner dans le canvas une forme (carré ou cercle) aux coordonnées données par le clic de souris dans le canvas.
Info
L'appel de la fonction cercle
va maintenant être réalisé par un événement extérieur (du type clavier ou souris). Il faut donc l'indiquer à la fonction en lui ajoutant le paramètre event
ou plus simplement evt
La méthode fen.mainloop()
en fin de programme permet d'écouter les événements extérieurs...
Exo
- Changer la fonction cercle comme suit:
🐍 Script Python
def cercle(evt): x, y = evt.x, evt.y r = valeur_curseur.get() Can.create_oval(x - r, y - r, x + r, y + r, fill = 'red')
- Ajouter enfin le code suivant juste avant l'instruction
fen.mainloop()
:🐍 Script PythonCan.bind("<Button-1>", cercle)
Vous comprendrez que:
- les coordonnées du clic de souris sont récupérées par les instructions
etv.x
etevt.y
. - la dernière instruction établit un lien entre le clic sur le bouton gauche de la souris (
Button-1
) et la fonctioncercle
sur le canvas.
Exo
Modifier les codes afin de construire un objet au clic de souris dans le canvas dont les formes, les couleurs et les dimensions sont données par les différents widgets.
Pilotage au clavier¶
Dans le paragraphe précédent, nous avons vu comment intéragir avec le clic de souris. Je vous propose ici de piloter un objet au clavier à l'aide des flèches directionnelles.
Exo
Récupérer le code ci-dessous et enregistrez le fichier sous le nom pilotage_cercle.py
Code à copier
from tkinter import *
####################### VARIABLES ##########################################
x, y = 400, 400 #défini les coordonnées initiales de l'objet
r = 25# défini le rayon initial
couleur = 'red'
######################### FONCTIONS #######################################
def bouge_balle(evt):
global x, y, r
touche = evt.keysym
if touche == "Left":
x = x - 2
can.coords(baballe, x - r, y - r, x + r, y + r)
elif touche == "Right":
x = x + 2
can.coords(baballe, x - r, y - r, x + r, y + r)
elif touche == "Up":
pass
elif touche == "Down":
pass
###################### CONSTRUCTEURS ###################################
fen = Tk()
fen.title( "Pilotage au clavier dans un canvas")
fen.geometry('800x800+100+100')
fen.resizable(False, False)
######################################################################################
can = Canvas(fen, bg = 'white', width = 800, height = 800)
can.grid()
######################################################################################
baballe = can.create_oval(x - r, y - r, x + r, y + r, fill = "red")
######################################################################################
fen.bind("<Key>", bouge_balle)
fen.mainloop()
Vous devriez être en mesure de piloter la balle rouge vers la gauche ou la droite. Quelques éléments qui méritent notre attention:
- l'instruction
fen.bind("<Key>", bouge_balle)
établit une lien entre l'action au clavier et la fonctionbouge_balle
; - l'instruction
touche = evt.keysym
permet d'affecter à la variabletouche
la valeur de la touche enfoncée au clavier; - l'instruction
can.coords(baballe,...)
change les coordonnées de l'objetbaballe
(qui existe!) dans le canvascan
.
Exo
Changer les instructions pass
de la fonction bouge_balle
pour piloter vers le haut et vers le bas la balle rouge.
Pour terminer ce travail, on se propose de faire évoluer la couleur la balle en appuyant sur les touches b
pour la couleur bleu, r
pour le rouge et n
pour le noir.
Exo
Ajouter deux cas à la fonction bouge_balle
pour modifier la couleur de la balle
Il faudra sans doute reconfigurer la balle...