使用 tkinter 跟踪 canvas 上每个多边形的每个点
Keeping track of each point of each polygon on a canvas with tkinter
我正在 UI 使用 tkinter 在 Python 中制作和 UI 七巧板(具有不同多边形的拼图),我想跟踪每个多边形的每个点的坐标他们在我的 canvas.
周围移动
为此,我创建了这个 class:
class Polygon:
def __init__(self, coords, color, canvas):
self.coords = coords
self.color = color
self.move = False
canvas.bind('<Button-1>', self.start_movement)
canvas.bind('<Motion>', self.movement)
canvas.bind('<ButtonRelease-1>', self.stopMovement)
canvas.bind('<Button-3>', self.rotate)
canvas.create_polygon(self.coords, fill=self.color)
每个多边形都是这样创建的:
medium_triangle = Polygon((0,0, 100*math.sqrt(2),0, 0,100*math.sqrt(2)),
'red', drawing_place)
small_triangle_1 = Polygon((0,0 ,100,0, 0,100), 'purple', drawing_place)
[...]
big_triangle_2 = Polygon((0,0, 200,0, 0,200), 'green', drawing_place)
我的主要问题是,看起来我只能修改最后创建的 Polygon
的 coords
属性。
我用鼠标拖动 canvas 上的棋子,然后使用这些方法让我的多边形移动:
def start_movement(self, event):
self.move = True
# Translate mouse coordinates to canvas coordinate
self.initi_x = drawing_place.canvasx(event.x)
self.initi_y = drawing_place.canvasy(event.y)
self.movingimage = drawing_place.find_closest(self.initi_x, self.initi_y,
halo=1) # get canvas object
# ID of where mouse
# pointer is.
def movement(self, event):
if self.move:
end_x = drawing_place.canvasx(event.x) # Translate mouse x screen
# coordinate to canvas coordinate.
end_y = drawing_place.canvasy(event.y) # Translate mouse y screen
# coordinate to canvas coordinate.
deltax = end_x - self.initi_x # Find the difference
deltay = end_y - self.initi_y # Find the difference
self.newPosition(deltax, deltay)
self.initi_x = end_x # Update previous current with new location
self.initi_y = end_y
drawing_place.move(self.movingimage, deltax, deltay) # Move object
def stopMovement(self, event):
self.move = False
affichage(self)
我设法将位移添加到我的初始坐标中,这要归功于我的 new_position 方法:
def newPosition(self, deltax, deltay):
coord = self.coords # Retrieve object points coordinates
old_coord = list(coord) # Tuple to List
c = [] # New coords
i = 0 # Cursor on old_coord
for coordinates in old_coord:
# check if index of coordinates in range of i and len(old_coord)
# in old_coord is pair (x coord).
if (old_coord.index(coordinates, i, len(old_coord)) % 2) == 0:
c.append(coordinates + deltax)
else: # index's impair => y-coord
c.append(coordinates + deltay)
i += 1
coord2 = tuple(c) # List to Tuple
self.set_coords(coord2)
def set_coords(self, coords):
self.coords = coords
但正如您在我的控制台中看到的那样
just after medium_triangle declaration:
(0, 0, 141.4213562373095, 0, 0, 141.4213562373095)
(0, 0, 200, 0, 0, 200)
(0, 0, 200, 0, 0, 200)
(0, 0, 200, 0, 0, 200)
(0, 0, 200, 0, 0, 200)
(297.0, 61.0, 497.0, 61.0, 297.0, 261.0)
(551.0, 166.0, 751.0, 166.0, 551.0, 366.0)
(951.0, 250.0, 1151.0, 250.0, 951.0, 450.0)
在声明我的多边形时,我似乎可以用 medium_triangle.coords
打印它们的坐标,但是之后,当我点击我的 canvas 时,它直接显示最后一个的坐标宣布。当我在 canvas 上移动另一块时,它只会添加到相同的 Polygon
.
我对 classes 和方法等不太满意,但我认为我明白我的每个多边形都是我的 class 的不同实例,但尽管如此,看起来我可以仅访问 Polygon
.
的一个实例
我希望我的问题很清楚,我真的创建了不同的多边形吗?如果是,为什么我不能单独修改它们?
canvas.bind('<Button-1>', self.start_movement)
canvas.bind('<Motion>', self.movement)
canvas.bind('<ButtonRelease-1>', self.stopMovement)
canvas.bind('<Button-3>', self.rotate)
您的 canvas(类型 Canvas
,或者我假设)只能绑定到每个键的一个操作。试试这个代码:
canvas.bind('<Button-1>', self.start_movement)
canvas.bind('<Button-1>', lambda e: print("ok"))
...您会发现它不再调用 start_movement()
,因为将调用 lambda。
在这里,唯一绑定到 canvas 的函数是您上次调用的函数:因此在您创建的最后一个 Polygon
的初始化中的函数。通过绑定新方法,您删除了以前对相同键的绑定。
您不应在 Polygon
class 中使用 canvas.bind(...)
。使用 canvas.tag_bind(...)
代替:
class Polygon:
def __init__(self, coords, color, canvas):
self.coords = coords
self.color = color
self.move = False
self.canvas = canvas
self.id = canvas.create_polygon(self.coords, fill=self.color)
canvas.tag_bind(self.id, '<Button-1>', self.start_movement)
canvas.tag_bind(self.id, '<Motion>', self.movement)
canvas.tag_bind(self.id, '<ButtonRelease-1>', self.stopMovement)
canvas.tag_bind(self.id, '<Button-3>', self.rotate)
请注意,我已将传递的 canvas
保存到实例变量 self.canvas
中。您应该在其他 class 方法中将所有 drawing_place
替换为 self.canvas
。
此外,您不需要在 start_movement()
中调用以下行:
self.movingimage = drawing_place.find_closest(self.initi_x, self.initi_y,
halo=1) # get canvas object
# ID of where mouse
# pointer is.
因为self.id
可以用来代替movement()
里面find_closest()
的结果:
def movement(self, event):
if self.move:
end_x = self.canvas.canvasx(event.x) # Translate mouse x screen
# coordinate to canvas coordinate.
end_y = self.canvas.canvasy(event.y) # Translate mouse y screen
# coordinate to canvas coordinate.
deltax = end_x - self.initi_x # Find the difference
deltay = end_y - self.initi_y # Find the difference
self.newPosition(deltax, deltay)
self.initi_x = end_x # Update previous current with new location
self.initi_y = end_y
self.canvas.move(self.id, deltax, deltay) # Move object
我正在 UI 使用 tkinter 在 Python 中制作和 UI 七巧板(具有不同多边形的拼图),我想跟踪每个多边形的每个点的坐标他们在我的 canvas.
周围移动为此,我创建了这个 class:
class Polygon:
def __init__(self, coords, color, canvas):
self.coords = coords
self.color = color
self.move = False
canvas.bind('<Button-1>', self.start_movement)
canvas.bind('<Motion>', self.movement)
canvas.bind('<ButtonRelease-1>', self.stopMovement)
canvas.bind('<Button-3>', self.rotate)
canvas.create_polygon(self.coords, fill=self.color)
每个多边形都是这样创建的:
medium_triangle = Polygon((0,0, 100*math.sqrt(2),0, 0,100*math.sqrt(2)),
'red', drawing_place)
small_triangle_1 = Polygon((0,0 ,100,0, 0,100), 'purple', drawing_place)
[...]
big_triangle_2 = Polygon((0,0, 200,0, 0,200), 'green', drawing_place)
我的主要问题是,看起来我只能修改最后创建的 Polygon
的 coords
属性。
我用鼠标拖动 canvas 上的棋子,然后使用这些方法让我的多边形移动:
def start_movement(self, event):
self.move = True
# Translate mouse coordinates to canvas coordinate
self.initi_x = drawing_place.canvasx(event.x)
self.initi_y = drawing_place.canvasy(event.y)
self.movingimage = drawing_place.find_closest(self.initi_x, self.initi_y,
halo=1) # get canvas object
# ID of where mouse
# pointer is.
def movement(self, event):
if self.move:
end_x = drawing_place.canvasx(event.x) # Translate mouse x screen
# coordinate to canvas coordinate.
end_y = drawing_place.canvasy(event.y) # Translate mouse y screen
# coordinate to canvas coordinate.
deltax = end_x - self.initi_x # Find the difference
deltay = end_y - self.initi_y # Find the difference
self.newPosition(deltax, deltay)
self.initi_x = end_x # Update previous current with new location
self.initi_y = end_y
drawing_place.move(self.movingimage, deltax, deltay) # Move object
def stopMovement(self, event):
self.move = False
affichage(self)
我设法将位移添加到我的初始坐标中,这要归功于我的 new_position 方法:
def newPosition(self, deltax, deltay):
coord = self.coords # Retrieve object points coordinates
old_coord = list(coord) # Tuple to List
c = [] # New coords
i = 0 # Cursor on old_coord
for coordinates in old_coord:
# check if index of coordinates in range of i and len(old_coord)
# in old_coord is pair (x coord).
if (old_coord.index(coordinates, i, len(old_coord)) % 2) == 0:
c.append(coordinates + deltax)
else: # index's impair => y-coord
c.append(coordinates + deltay)
i += 1
coord2 = tuple(c) # List to Tuple
self.set_coords(coord2)
def set_coords(self, coords):
self.coords = coords
但正如您在我的控制台中看到的那样
just after medium_triangle declaration:
(0, 0, 141.4213562373095, 0, 0, 141.4213562373095)
(0, 0, 200, 0, 0, 200)
(0, 0, 200, 0, 0, 200)
(0, 0, 200, 0, 0, 200)
(0, 0, 200, 0, 0, 200)
(297.0, 61.0, 497.0, 61.0, 297.0, 261.0)
(551.0, 166.0, 751.0, 166.0, 551.0, 366.0)
(951.0, 250.0, 1151.0, 250.0, 951.0, 450.0)
在声明我的多边形时,我似乎可以用 medium_triangle.coords
打印它们的坐标,但是之后,当我点击我的 canvas 时,它直接显示最后一个的坐标宣布。当我在 canvas 上移动另一块时,它只会添加到相同的 Polygon
.
我对 classes 和方法等不太满意,但我认为我明白我的每个多边形都是我的 class 的不同实例,但尽管如此,看起来我可以仅访问 Polygon
.
我希望我的问题很清楚,我真的创建了不同的多边形吗?如果是,为什么我不能单独修改它们?
canvas.bind('<Button-1>', self.start_movement)
canvas.bind('<Motion>', self.movement)
canvas.bind('<ButtonRelease-1>', self.stopMovement)
canvas.bind('<Button-3>', self.rotate)
您的 canvas(类型 Canvas
,或者我假设)只能绑定到每个键的一个操作。试试这个代码:
canvas.bind('<Button-1>', self.start_movement)
canvas.bind('<Button-1>', lambda e: print("ok"))
...您会发现它不再调用 start_movement()
,因为将调用 lambda。
在这里,唯一绑定到 canvas 的函数是您上次调用的函数:因此在您创建的最后一个 Polygon
的初始化中的函数。通过绑定新方法,您删除了以前对相同键的绑定。
您不应在 Polygon
class 中使用 canvas.bind(...)
。使用 canvas.tag_bind(...)
代替:
class Polygon:
def __init__(self, coords, color, canvas):
self.coords = coords
self.color = color
self.move = False
self.canvas = canvas
self.id = canvas.create_polygon(self.coords, fill=self.color)
canvas.tag_bind(self.id, '<Button-1>', self.start_movement)
canvas.tag_bind(self.id, '<Motion>', self.movement)
canvas.tag_bind(self.id, '<ButtonRelease-1>', self.stopMovement)
canvas.tag_bind(self.id, '<Button-3>', self.rotate)
请注意,我已将传递的 canvas
保存到实例变量 self.canvas
中。您应该在其他 class 方法中将所有 drawing_place
替换为 self.canvas
。
此外,您不需要在 start_movement()
中调用以下行:
self.movingimage = drawing_place.find_closest(self.initi_x, self.initi_y,
halo=1) # get canvas object
# ID of where mouse
# pointer is.
因为self.id
可以用来代替movement()
里面find_closest()
的结果:
def movement(self, event):
if self.move:
end_x = self.canvas.canvasx(event.x) # Translate mouse x screen
# coordinate to canvas coordinate.
end_y = self.canvas.canvasy(event.y) # Translate mouse y screen
# coordinate to canvas coordinate.
deltax = end_x - self.initi_x # Find the difference
deltay = end_y - self.initi_y # Find the difference
self.newPosition(deltax, deltay)
self.initi_x = end_x # Update previous current with new location
self.initi_y = end_y
self.canvas.move(self.id, deltax, deltay) # Move object