Función rotate tkinter python
Hola,
Me gustaría hacer girar un rectángulo creado con tkinter. He visto en muchos sitios que se utiliza la función rotate.
Mi código :
import tkinter as tk import math from functools import partial raiz = tk.Tk() #raiz es solo el nombre de la interfaz raiz.title("Optimización del tiempo de espera en los cruces") # Sirve para poner un título a la interfaz can1 = tk.Canvas( raiz, bg="white", height=1000, width=1000, borderwidth=0, highlightthickness=0 ) # Esto crea una zona can1.place(x=0, y=0) def dibujar(item, desp): #FUNCIÓN funciona can1.move(item, -desp, 0) raiz.after(50, dibujar, item, desp) item1 = can1.create_rectangle(620, 345, 635, 355, fill='orange', outline='') item1 = item1.rotate(45, None) raiz.mainloop() Pero en mi caso, aparece un mensaje de error :
No hay módulo llamado 'rotate' ¿Saben cómo hacerlo funcionar o tienen una solución alternativa?
Gracias de antemano
2 respuestas
hola,
yo obtengo un mensaje completamente diferente: "'int' object has no attribute 'rotate'".
Hola,
¿Estás seguro de que existe una función para hacer una rotación en Tk (¿tienes un enlace a la documentación que hable de ello? No puedo encontrarlo).
Ejemplo de partida
Un truco, propuesto aquí, dibuja un cuadrado negro y considera que el centro de rotación es el centro del cuadrado. Manteniendo el clic izquierdo del mouse, hacemos girar el cuadrado.
Bajo el capó, la función motion recalcula las nuevas coordenadas de los vértices del polígono (en función del centro y del ángulo de rotación). Veamos ahora cómo se realiza el cálculo.
Algunos recordatorios de matemáticas
El principio consiste en trasladar la figura de modo que la rotación se realice en (0, 0), y una vez realizada la rotación, volver a hacer la traducción en la dirección opuesta.
Método 1: con números complejos:
La implementación propuesta pasa por números complejos. La parte real corresponde a la coordenada en el eje x y la parte imaginaria a la coordenada en el eje y.
- Para aplicar una traducción (dx, dy) al punto (x, y), simplemente hay que calcular (x + i.y) + (dx + i.dy) = (x + y) + i.(dx + dy) lo que corresponde bien al punto (x + dx, y + dy).
- Una rotación del ángulo theta centrada en (0, 0) aplicada al punto (x, y) se obtiene multiplicando el número complejo x + i.y por el número complejo e^(i.theta) = cos(theta) + i.sin(theta) = (dx + i.dy) / |dx + i.dy|
Método 2: con números reales:
Si no te gustan los números complejos, puedes hacerlo con números reales y un poco de trigonometría:
- Una traducción se obtiene sumando directamente el par (dx, dy) a las coordenadas (x, y): (x, y) + (dx, dy) = (x + dx, y + dy)
- Para la rotación, hay que recurrir a las funciones trigonométricas. Una rotación centrada en (0, 0) de ángulo theta equivale a calcular (x * cos(theta) - y * sin(theta), x * sin(theta) + y * cos(theta)).
Código final (con números complejos)
from tkinter import * import math c = Canvas(width=200, height=200) c.pack() # Un cuadrado 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 # No se puede determinar el ángulo def motion(event): # Calcular el ángulo actual en relación al ángulo inicial 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() Utiliza el mouse para hacer girar el cuadrado negro.
Buena suerte
Eso también funciona, pero multiplicar cada punto por la matriz de rotación terminará reproduciendo el método 2 (además, una matriz 2x2 es suficiente ya que la transformación es invariante según Z). Gracias por cierto, esto me permitió corregir algunos errores en mi mensaje #3.