Rotate function tkinter python
Hello,
I would like to rotate a rectangle created with tkinter. I have seen on many sites that the rotate function was used.
My code:
import tkinter as tk import math from functools import partial root = tk.Tk() # root is just the name of the interface root.title("Optimization of waiting time at intersections") # Sets a title for the interface can1 = tk.Canvas( root, bg="white", height=1000, width=1000, borderwidth=0, highlightthickness=0 ) # This creates an area can1.place(x=0, y=0) def draw(item, move): # WORKS can1.move(item, -move, 0) root.after(50, draw, item, move) item1 = can1.create_rectangle(620, 345, 635, 355, fill='orange', outline='') item1 = item1.rotate(45, None) root.mainloop() But in my case, an error message appears:
No module named 'rotate' Do you know how to make it work or do you have an alternative solution?
Thank you in advance
2 answers
Hello,
I'm getting a completely different message: "'int' object has no attribute 'rotate'."
Hello,
Are you sure that there is a function for rotation in Tk (do you have a link to the documentation that mentions it, because I can't find any).
Starting example
A tip, proposed here, draws a black square and considers the center of rotation to be the center of the square. By holding down the left mouse button, we rotate the square.
Under the hood, the motion function recalculates the new coordinates of the polygon's vertices (based on the center and the rotation angle). Let's now see how the calculation is done.
Some math reminders
The principle consists of translating the figure so that the rotation takes place at (0, 0), and then once the rotation is done, translating back in the opposite direction.
Method 1: with complex numbers:
The proposed implementation uses complex numbers. The real part corresponds to the coordinate on the x-axis and the imaginary part to the coordinate on the y-axis.
- To apply a translation (dx, dy) to the point (x, y), simply calculate (x + i.y) + (dx + i.dy) = (x + y) + i.(dx + dy) which corresponds to the point (x + dx, y + dy).
- A rotation of angle theta centered at (0, 0) applied to the point (x, y) is obtained by multiplying the complex number x + i.y by the complex number e^(i.theta) = cos(theta) + i.sin(theta) = (dx + i.dy) / |dx + i.dy|
Method 2: with real numbers:
If you don't like complex numbers, you can manage with real numbers and a bit of trigonometry:
- A translation is obtained by directly adding the pair (dx, dy) to the coordinates (x, y): (x, y) + (dx, dy) = (x + dx, y + dy)
- For the rotation, you have to use trigonometric functions. A rotation centered at (0, 0) of angle theta comes down to calculating (x * cos(theta) - y * sin(theta), x * sin(theta) + y * cos(theta)).
Final code (with complex numbers)
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() Use the mouse to rotate the black square.
Good luck
It works too, but multiplying each point by the rotation matrix will ultimately reproduce method 2 (besides, a 2x2 matrix is sufficient since the transformation is invariant with respect to Z). Thanks by the way, it helped me correct a few mistakes in my message #3.