我想在python tkinter
中移动对象,特别是多边形。问题出在is_click
函数中。我似乎无法弄清楚如何确定是否点击了该对象。代码还没有100%完成,并且仍然需要完成移动,但我现在需要解决这个问题。我也有类似的类,你可以移动圆圈和矩形,其中is_click
函数正在工作,但由于多边形有3到4坐标,它有点复杂。为自己运行类,看看他们在做什么。
我的多边形代码:
import tkinter
class Polygon:
def __init__(self, ax, ay, bx, by, cx, cy, dx=None, dy=None, color=None):
self.ax = ax
self.ay = ay
self.bx = bx
self.by = by
self.cx = cx
self.cy = cy
self.dx = dx
self.dy = dy
self.color = color
def is_click(self, event_x, event_y):
pass
def paint(self, g):
self.g = g
if self.dx is None:
self.id = self.g.create_polygon(self.ax,self.ay,
self.bx,self.by,
self.cx,self.cy,
fill=self.color)
else:
self.id = self.g.create_polygon(self.ax,self.ay,
self.bx,self.by,
self.cx,self.cy,
self.dx,self.dy,
fill=self.color)
def move(self, d_ax=0, d_ay=0, d_bx=0, d_by=0, d_cx=0, d_cy=0, d_dx=None, d_dy=None):
if d_dx is None:
self.ax += d_ax
self.ay += d_ay
self.bx += d_bx
self.by += d_by
self.cx += d_cx
self.cy += d_cy
self.g.move(self.id, d_ax, d_ay, d_bx, d_by, d_cx, d_cy)
else:
self.ax += d_ax
self.ay += d_ay
self.bx += d_bx
self.by += d_by
self.cx += d_cx
self.cy += d_cy
self.dx += d_dx
self.dy += d_dy
self.g.move(self.id, d_ax, d_ay, d_bx, d_by, d_cx, d_cy, d_dx, d_dy)
class Tangram:
def __init__(self):
self.array = []
self.g = tkinter.Canvas(width=800,height=800)
self.g.pack()
#all objects
self.add(Polygon(500,300,625,175,750,300, color='SeaGreen'))
self.add(Polygon(750,50,625,175,750,300, color='Tomato'))
self.add(Polygon(500,175,562.6,237.5,500,300, color='SteelBlue'))
self.add(Polygon(500,175,562.5,237.5,625,175,562.5,112.5, color='FireBrick'))
self.add(Polygon(562.5,112.5,625,175,687.5,112.5, color='DarkMagenta'))
self.add(Polygon(500,50,500,175,625,50, color='Gold'))
self.add(Polygon(562.5,112.5,687.5,112.5,750,50,625,50, color='DarkTurquoise'))
#end of all objects
self.g.bind('<Button-1>', self.event_move_start)
def add(self, Object):
self.array.append(Object)
Object.paint(self.g)
def event_move_start(self, event):
ix = len(self.array) - 1
while ix >= 0 and not self.array[ix].is_click(event.x, event.y):
ix -= 1
if ix < 0:
self.Object = None
return
self.Object = self.array[ix]
self.ex, self.ey = event.x, event.y
self.g.bind('<B1-Motion>', self.event_move)
self.g.bind('<ButtonRelease-1>', self.event_release)
def event_move(self):
pass
def event_release(self):
pass
Tangram()
和Circle和Rectangle移动的代码:
import tkinter, random
class Circle:
def __init__(self, x, y, r, color='red'):
self.x = x
self.y = y
self.r = r
self.color = color
def is_click(self, x, y):
return (self.x-x)**2+(self.y-y)**2 < self.r**2
def paint(self, g):
self.g = g
self.id = self.g.create_oval(self.x-self.r,self.y-self.r,
self.x+self.r,self.y+self.r,
fill=self.color)
def move(self, dx=0, dy=0):
self.g.delete(self.id)
self.x += dx
self.y += dy
self.paint(self.g)
class Rectangle:
def __init__(self, x, y, width, height, color='red'):
self.x = x
self.y = y
self.width = width
self.height = height
self.color = color
def is_click(self, x, y):
return self.x<=x<self.x+self.width and self.y<=y<self.y+self.height
def paint(self, g):
self.g = g
self.id = self.g.create_rectangle(self.x,self.y,
self.x+self.width,self.y+self.height,
fill=self.color)
def move(self, dx=0, dy=0):
self.x += dx
self.y += dy
self.g.move(self.id, dx, dy)
class Program:
def __init__(self):
self.array = []
self.g = tkinter.Canvas(bg='white', width=400, height=400)
self.g.pack()
for i in range(20):
if random.randrange(2):
self.add(Circle(random.randint(50, 350),random.randint(50, 350), 20, 'blue'))
else:
self.add(Rectangle(random.randint(50, 350),random.randint(50, 350), 40, 30))
self.g.bind('<Button-1>', self.event_move_start)
def add(self, Object):
self.array.append(Object)
Object.paint(self.g)
def event_move_start(self, e):
ix = len(self.array)-1
while ix >= 0 and not self.array[ix].is_click(e.x, e.y):
ix -= 1
if ix < 0:
self.Object = None
return
self.Object = self.array[ix]
self.ex, self.ey = e.x, e.y
self.g.bind('<B1-Motion>', self.event_move)
self.g.bind('<ButtonRelease-1>', self.event_release)
def event_move(self, e):
self.Object.move(e.x-self.ex, e.y-self.ey)
self.ex, self.ey = e.x, e.y
def event_release(self, e):
self.g.unbind('<B1-Motion>')
self.g.unbind('<ButtonRelease-1>')
self.Object = None
Program()
答案 0 :(得分:0)
这不是你问题的完整答案,但是评论的时间太长了。我会集中考虑的一种方法是更改/修改代码,以便它使用find_closes方法。使用此方法,您可以非常轻松地确定单击哪个窗口小部件(即多边形)。作为一个快速概念,您可以在Tangram和ploygon类中进行以下更改:
def event_move_start(self, event):
ix = len(self.array) - 1
while ix >= 0 and not self.array[ix].is_click(event, self.g, event.x, event.y): # add event and canvas to argumetns
在多边形中:
def is_click(self, event, g, event_x, event_y):
widget_id = event.widget.find_closest(event.x, event.y)
print(widget_id)
g.move(widget_id, 1, 1) # just dummy move for a clicked widget
pass
这将打印单击的小部件/多边形的ID,并稍微移动单击的多边形。这可用于选择单击的对象,并具有此id对象,您可以移动或其他任何。
P.S。我用来测试它的完整代码是here。
希望这有帮助。