Python 在Tkinter画布上旋转正方形
我已经接近了,但有两个问题。一个是旋转正方形的最终位置(不再位于中心)。第二个是我的原始顶点列表发生了变化,尽管我使用列表(..)制作了一个副本 如往常一样,非常感谢您的帮助Python 在Tkinter画布上旋转正方形,python,list,tkinter-canvas,Python,List,Tkinter Canvas,我已经接近了,但有两个问题。一个是旋转正方形的最终位置(不再位于中心)。第二个是我的原始顶点列表发生了变化,尽管我使用列表(..)制作了一个副本 如往常一样,非常感谢您的帮助 from Tkinter import * import math WIDTH = 400 HEIGHT = 400 CANVAS_MID_X = WIDTH/2 CANVAS_MID_Y = HEIGHT/2 SIDE = WIDTH/4 root = Tk() canvas = Canvas(root, bg="
from Tkinter import *
import math
WIDTH = 400
HEIGHT = 400
CANVAS_MID_X = WIDTH/2
CANVAS_MID_Y = HEIGHT/2
SIDE = WIDTH/4
root = Tk()
canvas = Canvas(root, bg="black", height=HEIGHT, width=WIDTH)
canvas.pack()
vertices = [
[CANVAS_MID_X - SIDE/2, CANVAS_MID_Y - SIDE/2],
[CANVAS_MID_X + SIDE/2, CANVAS_MID_Y - SIDE/2],
[CANVAS_MID_X + SIDE/2, CANVAS_MID_Y + SIDE/2],
[CANVAS_MID_X - SIDE/2, CANVAS_MID_Y + SIDE/2]]
def rotate(points, angle):
new_points = list(points)
rad = angle * (math.pi/180)
cos_val = math.cos(rad)
sin_val = math.sin(rad)
for coords in new_points:
x_val = coords[0]
y_val = coords[1]
coords[0] = x_val * cos_val - y_val * sin_val
coords[1] = x_val * sin_val + y_val * cos_val
return new_points
def draw_square(points):
canvas.create_polygon(points, fill="red")
def test():
print "vertices: ", vertices, "should be: ", "[[150, 150], [250, 150], [250, 250], [150, 250]]"
new_square = rotate(vertices, 30)
draw_square(new_square)
test()
mainloop()
第一个问题是,您使用的公式围绕原点旋转。我假设你想绕着正方形的中心旋转。为此,只需平移正方形,使其中心位于原点,旋转它,然后将其平移回原点 第二个问题是,执行
list(points)
会创建一个新的外部列表,但不会为points
内的列表创建新列表。有很多方法可以创建一个深度副本,为那些内部列表创建新的列表,但在这里您并不需要这样做。只需从旋转的顶点构建一个新列表
我的代码版本将原始正方形绘制为蓝色,这样我们可以看到旋转后的正方形最终位于正确的位置
from Tkinter import *
import math
WIDTH = 400
HEIGHT = 400
CANVAS_MID_X = WIDTH/2
CANVAS_MID_Y = HEIGHT/2
SIDE = WIDTH/4
root = Tk()
canvas = Canvas(root, bg="black", height=HEIGHT, width=WIDTH)
canvas.pack()
vertices = [
[CANVAS_MID_X - SIDE/2, CANVAS_MID_Y - SIDE/2],
[CANVAS_MID_X + SIDE/2, CANVAS_MID_Y - SIDE/2],
[CANVAS_MID_X + SIDE/2, CANVAS_MID_Y + SIDE/2],
[CANVAS_MID_X - SIDE/2, CANVAS_MID_Y + SIDE/2],
]
def rotate(points, angle, center):
angle = math.radians(angle)
cos_val = math.cos(angle)
sin_val = math.sin(angle)
cx, cy = center
new_points = []
for x_old, y_old in points:
x_old -= cx
y_old -= cy
x_new = x_old * cos_val - y_old * sin_val
y_new = x_old * sin_val + y_old * cos_val
new_points.append([x_new + cx, y_new + cy])
return new_points
def draw_square(points, color="red"):
canvas.create_polygon(points, fill=color)
def test():
old_vertices = [[150, 150], [250, 150], [250, 250], [150, 250]]
print "vertices: ", vertices, "should be: ", old_vertices
print vertices == old_vertices
draw_square(vertices, "blue")
center = (CANVAS_MID_X, CANVAS_MID_Y)
new_square = rotate(vertices, 30, center)
test()
draw_square(new_square)
mainloop()
我还对你的代码做了一些其他的小改动
顺便说一句,你可能应该这样做
from __future__ import division
在其他导入之前。这告诉Python使用真正的除法。没有它,SIDE/2
进行整数除法。这在这里可以,但如果SIDE
是奇数,则不正确
你应该努力改掉做某事的习惯
from Tkinter import *
相反,你应该这样做
import Tkinter as tk
然后调用Tkinter函数,如下所示:
canvas = tk.Canvas(root, bg="black", height=HEIGHT, width=WIDTH)
这稍微需要更多的键入,但它使代码更易于阅读和维护,并防止在代码意外使用Tkinter定义的名称之一时发生错误。FWIW,从Tkinter import*执行
操作将超过170个名称导入到您的命名空间中。你不需要那些乱七八糟的东西 感谢您清楚地解释您的问题,并发布一个!爱死它了!谢谢在我学习的这个阶段,这种“超越基础”的答案确实非常有用。这不是旋转正方形,而是用旋转的坐标创建另一个正方形。例如,当你想要一个动画,其中一个正方形移动到某个点,旋转并向另一个方向移动时,这是没有用的。@Pagol好吧,这正是Robin想要的。;)如果你有一个关于以你描述的方式旋转Tkinter画布对象的新问题,那么你应该问一个新问题(当然,在第一次检查以确保这样的问题不存在之后)。旋转几何对象应该是非常常见的操作,应该有一些内置函数。如果没有,则需要在lib中创建并添加它。