Nous allons ici mettre en place, à l'aide d'exemples, de très nombreuses techniques, pas toujours simples à comprendre, et encore moins à reproduire ensuite.
Pour en tirer profit, et pouvoir les ré-exploiter dans les projets, il faudra impérativement :
tout le temps "perdu" ici, sera regagné 100 fois sur le projet !
|
#################### 1) Importation ####################
# Importation du module tkinter :
from tkinter import *
#################### 2) Main ####################
# Création de la fenêtre principale : objet Tk() stocké dans une variable fen :
fen = Tk()
# Lancement du gestionnaire d'événements
fen.mainloop()
Désormais nos programmes ne sont plus destinés à être exécutés de la première à la dernière ligne mais à comporter tous les blocs d'instructions nécessaires pour répondre aux actions de l'utilisateur au clavier, à la souris, au joystick ...
Ainsi, dans un jeu vidéo, nous souhaitons, par exemple, que Mario Bros tourne à droite lorsque le joueur pousse son joystick vers la droite.
Nos programmes doivent désormais être pilotés par les événements qui se produisent (au clavier, à la souris, au joystick ...).
Pour cela, nous devons céder la main à un réceptionnaire d'événements, capable de capter les actions de l'utilisateur et de les transmettre au programme pour les traiter.
C'est le rôle de l'instruction fen.mainloop() : il s'agit d'une boucle infinie qui va tourner jusqu'à la fermeture de la fenêtre, pour capter et transmettre toutes les actions de l'utilisateur.
#################### 1) Importation ####################
# Importation du module tkinter :
from tkinter import *
#################### 2) Main ####################
# Création de la fenêtre principale : objet Tk() stocké dans une variable fen :
fen = Tk()
# Création d'un widget Button (bouton Quitter)
bouton1 = Button(fen, text = 'Quitter', command = fen.destroy)
# Positionnement du widget dans la fenêtre avec la méthode pack() :
bouton1.pack()
# Lancement du gestionnaire d'événements
fen.mainloop()
Remarques :
1. Examinons l'instruction : bouton1 = Button(fen, text = 'Quitter', command = fen.destroy)
Elle signifie : créer un widget « bouton poussoir », dans la fenêtre « fen », portant le texte « Quitter », et dont le résultat lorsqu'on l'actionne sera la commande « fen.destroy ».
2. On notera que de nombreuses actions sont désormais réalisées selon la syntaxe suivante :
objet.methode()
fen.destroy()
#################### 1) Importation ####################
# Importation du module tkinter :
from tkinter import *
#################### 2) Main ####################
# Création de la fenêtre principale : objet Tk() stocké dans une variable fen :
fen = Tk()
# Création d'un widget Label (texte 'Bonjour tout le monde !')
label1 = Label(fen, text = 'Bonjour tout le monde !', fg = 'red')
# Positionnement du widget avec la méthode pack()
label1.pack()
# Lancement du gestionnaire d'événements
fen.mainloop()
fg : foreground (premier plan) : permet de choisir la couleur du texte.
#################### 1) Importation ####################
# Importation de la bibliothèque tkinter
from tkinter import *
#################### 2) Main ####################
# Création d'une fenêtre graphique stockée dans la variable fen :
fen=Tk()
# Création du widget Canvas :
can=Canvas(fen, bg='bisque', heigh=400, width=600)
# Positionnement du Canvas dans la fenêtre:
can.pack()
# On cède la main au réceptionnaire d’événements :
fen.mainloop()
bg : background : arrière-plan : permet de choisir la couleur du fond ,
height : hauteur en pixels du canevas souhaité,
width : largeur en pixels du canevas souhaité.
can.create_oval(200,100,400,300, outline='red', fill='blue')
can.create_rectangle(200,100,400,300, outline='black', width=2)
can.create_line(0,0,600,400, fill='pink', width=4)
can.bind("<Button-1>", explose)
def explose(event) :
...
################## 1) Importation de tkinter ##################
from tkinter import *
################# 2) Définition des fonctions #################
# La fonction position ci-dessous va modifier notre Label chaine
# pour indiquer la position du clic.
# event.x : récupére l'abscisse de l'événement clic gauche
# event.y : récupère l'ordonnée de l'événement clic gauche
def position(event):
chaine.configure(text = "Clic détecté en X =" + str(event.x) + ", Y =" + str(event.y))
############################ 3) MAIN ############################
# Création de la fenêtre :
fen = Tk()
# Création et positionnement du canevas :
can = Canvas(fen, width =600, height =500, bg="light yellow")
can.pack()
# Création et positionnement d'un label :
chaine = Label(fen)
chaine.pack()
# La méthode bind va lier l'événement clic gauche au canevas,
# déclenchant alors la fonction position.
can.bind("<Button-1>", position)
# On cède la main au réceptionnaire d'événements :
fen.mainloop()
Remarques :
can.coords(objet_à_déplacer, new_x1, new_y1, new_x2, new_y2)
Exemple :
Nous allons ici lier l'événement "appui sur la flèche droite" à la fenêtre, le gestionnaire de l'événement étant alors la fonction avance.
Testons le programme suivant :
######### 1) Importation ##############################
from tkinter import *
######### 2) Fonctions ################################
def avance(event) :
global x
x = x + 50
can.coords(bal, x, 200, x + 50, 250) # la méthode coords du canevas permet de déplacer
# un objet à préciser (ici bal),
# vers une nouvelle position, ici :
# la boite de points extrèmes : (x;200) et (x+50;250)
######## 3) Main ######################################
# Création de la fenêtre et du canevas :
fen = Tk()
can = Canvas(fen, width = 600, height = 450, bg = 'ivory')
can.pack()
# Création de l'abscisse "x" de la balle et de la balle "bal" :
x = 0
bal = can.create_oval(x, 200, x + 50, 250, fill='blue')
# Mise en place du binding :
fen.bind("<Right>", avance) # la fonction avance sera appelée à chaque fois
# que l'on appuiera sur la touche "flèche droite".
# On cède la main au réceptionnaire d'événements :
fen.mainloop()
Remarquons ici qu'afin de pouvoir modifier l'abscisse "x" de la balle à l'intérieur de la fonction "avance", nous avons dû déclarer, dans la fonction "avance", qu'elle utiliserait la variable "x" comme une variable globale.
can.move(NomItem, dx, dy)
Déplace l'item concerné en ajoutant dx à son abscisse x, et dy à son ordonnées y.
######### 1) Importation ##############################
from tkinter import *
######### 2) Fonctions ################################
def moove() :
global x
x = x + 50
can.coords(bal, x, 200, x + 50, 250)
fen.after(500, moove) # appeler à nouveau la fonction moove 500 ms plus tard
######## 3) Main ######################################
# Création de la fenêtre et du canevas :
fen = Tk()
can = Canvas(fen, width = 600, height = 450, bg = 'ivory')
can.pack()
# Création de l'abscisse "x" de la balle et de la balle "bal" :
x = 0
bal = can.create_oval(x, 200, x + 50, 250, fill='blue')
# On lance la fonction d'animation :
moove()
# On cède la main au réceptionnaire d'événements :
fen.mainloop()
La méthode "after" peut s'appliquer à un widget quelconque.
Nous l'appliquons ici à la fenêtre "fen" qui déclenche alors l'appel d'une fonction après un certain temps à préciser (ici 500 ms) :
fen.after(500, moove)
Dans le programme ci-dessus, alors que nous sommes déjà dans la fonction "moove", la fonction qui est appelée par la méthode "after" est la fonction "moove" elle-même : la fonction moove se ré-appelle elle-même !
La fonction sera donc relancée 500 ms plus tard, re-fera bouger la balle, et se ré-appellera 500 ms plus tard, et ainsi de suite ...
Nous lançons ainsi une boucle infinie : toutes les 500 ms, la fonction moove sera relancée.
En informatique, on appelle cela une fonction récursive : une fonction s'appelle elle-même.