Fonction rotate tkinter python

Fermé
ol3256457 - Modifié le 3 nov. 2022 à 13:12
mamiemando Messages postés 33363 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 16 novembre 2024 - 3 nov. 2022 à 16:59

Bonjour,

J'aimerais faire tourner un rectangle créé avec tkinter. J'ai vu sur beaucoup de sites que la fonction rotate était utilisée.

Mon code :

import tkinter as tk
import math
from functools import partial

racine = tk.Tk() #racine c'est juste le nom de l'interface
racine.title("Optimisation du temps d'attente aux carrefours") # Sert à mettre une titre à l'interface

can1 = tk.Canvas(
    racine,
    bg="white",
    height=1000,
    width=1000,
    borderwidth=0,
    highlightthickness=0
) # Ça crée une zone
can1.place(x=0, y=0)

def dessiner(item, depl): #FONCTIONNE
    can1.move(item, -depl, 0)
    racine.after(50, dessiner, item, depl)

item1 = can1.create_rectangle(620, 345, 635, 355, fill='orange', outline='')
item1 = item1.rotate(45, None)
racine.mainloop()

Mais dans mon cas, un message d'erreur s'affiche :

No module named 'rotate'

Savez-vous comment la faire fonctionner ou avez vous une solution alternative ?

Merci par avance

A voir également:

2 réponses

yg_be Messages postés 23329 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 17 novembre 2024 Ambassadeur 1 551
3 nov. 2022 à 12:49

bonjour,

moi j'obtiens un tout autre message: "'int' object has no attribute 'rotate'".

0
mamiemando Messages postés 33363 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 16 novembre 2024 7 801
Modifié le 3 nov. 2022 à 17:02

Bonjour,

Tu es sûr qu'il existe une fonction pour faire une rotation en Tk (as-tu un lien vers la documentation qui en parle, car je n'en trouve pas).

Exemple de départ

Une astuce, proposée ici, dessine un carré noir et considère que le centre de la rotation est le centre du carré. En maintenant le clic gauche de la souris, on fait pivoter le carré.

Sous le capot, la fonction motion recalcule les nouvelles coordonnées des sommets du polygone (en fonction du centre et de l'angle de rotation). Voyons maintenant comment le calcul est fait.

Quelques rappels de maths

Le principe consiste à translater la figure de sorte à ce que la rotation se fasse en (0, 0), puis une fois la rotation faite, refaire la translation dans le sens opposé.

Méthode 1 : avec des nombres complexes :

L'implémentation proposée passe par des nombres complexes. La partie réelle correspond à la coordonnée sur l'axe x et la partie imaginaire à la coordonnée sur l'axe y.

  • Pour appliquer une translation (dx, dy) au point (x, y), il suffit donc de calculer (x + i.y) + (dx + i.dy) = (x + y) + i.(dx + dy) ce qui correspond bien au point (x + dx, y + dy).
  • Une rotation de l'angle theta centrée en (0, 0) appliquer au point (x, y) s'obtient en multipliant le nombre complexe x + i.y par le nombre complexe e^(i.theta) = cos(theta) + i.sin(theta) = (dx + i.dy) / |dx + i.dy|

Méthode 2 : avec des nombres réels :

Si tu n'aimes pas les nombres complexes, tu peux t'en sortir avec des nombres réels et un eu de trigonométrie :

  • Une translation s'obtient en ajoutant directement le couple (dx, dy) au coordonnées (x, y) : (x, y) + (dx, dy) = (x + dx, y + dy)
  • Pour la rotation, il faut passer par les fonctions trigonométriques. Une rotation centrée en (0, 0) d'angle theta revient à calculer (x * cos(theta) - y * sin(theta), x * sin(theta) + y * cos(theta)).

Code final (avec des nombres complexes)

from tkinter import *
import math

c = Canvas(width=200, height=200)
c.pack()

# A square
center = (100, 100)
points = [(50, 50), (150, 50), (150, 150), (50, 150)]
polygon_item = c.create_polygon(points)

def get_angle(event):
    dx = c.canvasx(event.x) - center[0]
    dy = c.canvasy(event.y) - center[1]
    try:    
        return complex(dx, dy) / abs(complex(dx, dy))
    except ZeroDivisionError:
        return 0.0 # Cannot determine angle

def motion(event):
    # Calculate current angle relative to initial angle
    angle = get_angle(event)
    if angle == 0.0:
        return
    offset = complex(center[0], center[1])
    new_points = []
    for (x, y) in points:
        v = angle * (complex(x, y) - offset) + offset
        new_points.append(v.real)
        new_points.append(v.imag)
    c.coords(polygon_item, *new_points)

c.bind("<B1-Motion>", motion) 

mainloop()

Utilise la souris pour faire pivoter le carré noir.

Bonne chance

0
Phil_1857 Messages postés 1872 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 168
Modifié le 3 nov. 2022 à 15:02

Bonjour,

Ou alors tu crées une matrice de rotation sur Z (donc dans le plan XY), de la valeur de l'angle, et 

tu l'appliques à chaque coordonnée du rectangle

(multiplication d'un point par une matrice)

0
mamiemando Messages postés 33363 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 16 novembre 2024 7 801 > Phil_1857 Messages postés 1872 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024
Modifié le 3 nov. 2022 à 17:03

Ça marche aussi, mais multiplier chaque point par la matrice de rotation reviendra à la fin à reproduire la méthode 2 (d'ailleurs une matrice 2x2 suffit puisque la transformation est invariante selon Z). Merci au passage ça m'a permis de corriger quelques erreurs dans mon message #3.

0