tkinter : polygone et translation

Nous voyons ici comment dessiner des polygones, puis comment les animer un peu.

Définir un rectangle

On définit un rectangle de côtés parallèles à la fenêtre avec create_rectangle, on précise pour cela les coordonnées du point supérieur gauche et les coordonnées du sommet opposé (inférieur droit).

Testez le code suivant. Modifiez le pour être certain de bien saisir le rôle des paramètres.


import tkinter 
import tkinter.colorchooser 


def couleurInterieur() :
	""" lance une fenêtre de sélection d'une couleur. Modifie la variable 
	couleurremplissage avec la couleur choisie."""
	global couleurremplissage 
	c = tkinter.colorchooser.askcolor()
	couleurremplissage = c[1] 
	
def couleurContour() :
	""" lance une fenêtre de sélection d'une couleur. Modifie la variable 
	couleurbordure avec la couleur choisie."""
	global couleurbordure 
	c = tkinter.colorchooser.askcolor()
	couleurbordure = c[1]
	
	
def recolorierRectangle():
	""" Modifie les attributs couleurs de rectangle1."""
	canevas.itemconfig(rectangle1, fill = couleurremplissage, outline = couleurbordure)


fenetre = tkinter.Tk() 
# définition d'une zone de dessin dans la fenêtre tkinter :
largeur = 150
hauteur = 150 
canevas = tkinter.Canvas(fenetre, width = largeur, height = hauteur)
canevas.pack()
 
 
couleurremplissage = '' # pas de remplissage au départ
couleurbordure = 'black' # frontière noire au départ
# définition d'un rectangle, côtés parallèles à la fenêtre, de sommets haut-gauche A(10,10)
# et de sommet opposé (bas-droit) B(50, 100) :
rectangle1 = canevas.create_rectangle(10,10, 50,100, 
fill = couleurremplissage, outline = couleurbordure , width=4)



bouton1 = tkinter.Button(fenetre, text = "Couleur de remplissage", command = couleurInterieur) 
bouton1.pack() 

bouton2 = tkinter.Button(fenetre, text = "Couleur de contour", command = couleurContour) 
bouton2.pack() 

bouton3 = tkinter.Button(fenetre, text = "Recolorier le rectangle", command = recolorierRectangle) 
bouton3.pack() 
 
fenetre.mainloop() 

un rectangle

Un autre exemple est donné ci-dessous pour la création de rectangles. Testez.


import tkinter 
import random as rd



# fenêtre principale
fenetre = tkinter.Tk()
# dimensions de l'écran :  
ll = fenetre.winfo_screenwidth() 
hh = fenetre.winfo_screenheight() 
# canvas prenant toute la fenêtre :
canevas = tkinter.Canvas(fenetre, width = ll, height = hh)
canevas.pack()



 

def rectangleHasard(zone) :
    """
    le paramètre zone est de type canvas.
    création d'un rectangle de coin supérieur gauche (cx,cy) choisi au hasard
    largeur et hauteur du rectangle au hasard
    """
    largeur = zone.winfo_reqwidth() # largeur du canvas zone
    hauteur = zone.winfo_reqheight()  # hauteur du canvas zone
    cx = rd.random()*largeur
    cy = rd.random()*hauteur
    l = rd.random()*largeur/5
    h = rd.random()*hauteur/5
    zone.create_rectangle(cx,cy, cx+l,cy+h, fill = 'white', outline = 'grey' , width=4)
    


nbRectangles = 5000
for _ in range(nbRectangles) :
    rectangleHasard(canevas) 
    # attente d'une milliseconde et rafraichissement de l'affichage :
    # (sans cela, les rectangles s'affichent tous d'un coup en fin de boucle)
    fenetre.after(1,fenetre.update())
    
    
fenetre.mainloop() 
ils sont beaux mes rectangles

Définir un polygone

On définit un polygone par create_polygon. Les premiers paramètres sont les coordonnées des sommets, chaque sommet est relié au suivant par un segment, le dernier est relié au premier.

On peut préciser la couleur de remplissage avec fill, la couleur des contours avec outline, l'épaisseur du trait de contour avec width.


import tkinter 

fenetre = tkinter.Tk() 
# définition d'une zone de dessin dans la fenêtre tkinter :
largeur = 150
hauteur = 150 
canevas = tkinter.Canvas(fenetre, width = largeur, height = hauteur)
canevas.pack()
 
 
# définition d'un polygone de sommets A(10,10), B(20,20), C(100,50), D(20,100) :
canevas.create_polygon(10,10,20,20,100,50,20,100, fill='', outline='green', width=2)
 
 
fenetre.mainloop()

polygone

Translater un polygone

Testez et étudiez l'exemple ci-dessous.


import tkinter 

def translate() :
	""" On translate chaque sommet du polygone1 par la translation de vecteur u( xu, yu )."""
	global xa,ya,xb,yb,xc,yc  
	xu = ux.get() # on récupère la valeur donnée au curseur ux
	yu = uy.get() # on récupère la valeur donnée au curseur uy
	xa, ya = xa+xu, ya+yu # nouvelles coordonnées du sommet A
	xb, yb = xb+xu, yb+yu # nouvelles coordonnées du sommet B
	xc, yc = xc+xu, yc+yu # nouvelles coordonnées du sommet C
	# on rédéfinit polygone1 :
	canevas.coords(polygone1, xa, ya, xb, yb, xc, yc)
	
 
fenetre = tkinter.Tk() 
 	
# définition d'une zone de dessin dans la fenêtre tkinter :
largeur = 500
hauteur = 500 
canevas = tkinter.Canvas(fenetre, width = largeur, height = hauteur)
canevas.pack()
 
# définition d'un triangle de sommets A(xa,ya), B(xb,yb), C(xc,yc) :
xa, ya = 0, 0
xb, yb = 10, 10
xc, yc = 0, 20
polygone1 = canevas.create_polygon(xa,ya, xb,yb,xc,yc, fill='red')

# on définit un curseur pour que l'utilisateur puisse indiquer 
# l'abscisse du vecteur de translation :
ux = tkinter.DoubleVar()
scale = tkinter.Scale(fenetre, variable = ux,from_ = -20, to = 20,resolution = 0.5)
# on affiche le curseur sur la gauche de la fenêtre :
scale.pack(side = 'left')

# on définit un curseur pour que l'utilisateur puisse indiquer 
# l'ordonnée du vecteur de translation :
uy = tkinter.DoubleVar()
scale = tkinter.Scale(fenetre, variable = uy, from_ = -20, to = 20, resolution = 0.5)
# on affiche le curseur sur la droite de la fenêtre :
scale.pack(side = 'right')
 
# définition d'un bouton à cliquer ayant pour effet une translation du triangle
# translation définie par les curseurs 
bouton = tkinter.Button(fenetre, text = "translatez le triangle", command = translate  ) 
bouton.pack()
 
fenetre.mainloop()

Translation 'animée'

Testez et étudiez l'exemple ci-dessous.


import time
import tkinter

# fenêtre tkinter
# dans laquelle on peut placer canevas, boutons...
fenetre = tkinter.Tk()

# ouverture d'un canevas sur fond blanc
canevas =  tkinter.Canvas(fenetre, width = 500, height = 500)
canevas.configure(bg = "white")
canevas.pack()


# création de deux triangles 
triangle1 = canevas.create_polygon(5,5,20,20,5,15, fill = 'orange')
triangle2 = canevas.create_polygon(400,400, 420,420, 400, 420, fill = 'brown')


# déplacements successifs : 
for i in range(60) :
	# translation de 5px en abscisse et 5px en ordonnée du triangle 1 :
	canevas.move(triangle1, 5,5)
	# translation de -5px en abscisse et -5px en ordonnée du triangle 2 :
	canevas.move(triangle2, -5,-5)
	# rafraîchissement de la fenêtre (indispensable, sinon le tracé
	# n'est fait qu'en fin de boucle et on ne verra que la position finale)
	fenetre.update()
	#léger temps d'attente pour voir le mouvement 
	time.sleep(0.05)
	

fenetre.mainloop()

Plutôt que time.sleep, il est préférable d'utiliser after du module tkinter, ce qui donne :


import tkinter

# fenêtre tkinter
# dans laquelle on peut placer canevas, boutons...
fenetre = tkinter.Tk()

# ouverture d'un canevas sur fond blanc
canevas =  tkinter.Canvas(fenetre, width = 500, height = 500)
canevas.configure(bg = "white")
canevas.pack()


# création de deux triangles 
triangle1 = canevas.create_polygon(5,5,20,20,5,15, fill = 'orange')
triangle2 = canevas.create_polygon(400,400, 420,420, 400, 420, fill = 'brown')


# déplacements successifs : 
for i in range(60) :
	# translation de 5px en abscisse et 5px en ordonnée du triangle 1 :
	canevas.move(triangle1, 5,5)
	# translation de -5px en abscisse et -5px en ordonnée du triangle 2 :
	canevas.move(triangle2, -5,-5)
	# rafraîchissement de la fenêtre tous les 5 centièmes de secondes :
	fenetre.after(50,fenetre.update())
	  
fenetre.mainloop()

Vous pouvez maintenant pratiquer un peu.