Python canvas.itemconfig导致无限事件循环
我试着在每个单元格上画一块3x3的小黑板,上面有一个标记。 仅当鼠标触摸单元格时,此标记才会显示。 这可以工作一次,两次,有时三次-但是随后事件循环无限地“激发”(总是相同的事件)Python canvas.itemconfig导致无限事件循环,python,tkinter,python-3.5,tkinter-canvas,Python,Tkinter,Python 3.5,Tkinter Canvas,我试着在每个单元格上画一块3x3的小黑板,上面有一个标记。 仅当鼠标触摸单元格时,此标记才会显示。 这可以工作一次,两次,有时三次-但是随后事件循环无限地“激发”(总是相同的事件) 将tkinter作为tk导入 单元大小=50 课程板(tk.Canvas): 定义初始化(自): tk.Canvas.\uuuuu init\uuuuuuuu(自) 对于范围(3)中的行: 对于范围(3)中的列: ulx,uly=列*单元大小,行*单元大小 lrx,lry=ulx+cellsize,uly+cells
将tkinter作为tk导入
单元大小=50
课程板(tk.Canvas):
定义初始化(自):
tk.Canvas.\uuuuu init\uuuuuuuu(自)
对于范围(3)中的行:
对于范围(3)中的列:
ulx,uly=列*单元大小,行*单元大小
lrx,lry=ulx+cellsize,uly+cellsize
_单元格=自身。创建矩形(ulx、uly、lrx、lry、,
填充(绿色)
_右=自身。创建矩形(ulx+39、uly+20、lrx-1、lry-20、,
填写“红色”,
状态(隐藏)
self.tag_bind(_单元格,
lambda e,r=_right:self.show_pos('on',r))
self.tag_bind(_单元格,
lambda e,r=_right:self.show_pos('off',r))
def显示位置(自身、接通断开、右侧):
打印({}{}.format(onoff,右))
如果onoff==“on”:
self.itemconfig(右,state='normal')
elif onoff==“off”:
self.itemconfig(右,state='hidden')
root=tk.tk()
Board().grid()
root.mainloop()
这可能是因为执行其他操作(例如更新状态行)可以按预期工作,所以会被粘贴到self.itemconfigure语句中
有解决办法吗
提前Thx
马文
添加:更准确地说:它似乎坚持使用“state=…”
在“show_pos”中将itemconfig更改为“fill=…”,效果与预期一样。 所以标题应该是
“canvas.itemconfig(state=”…“导致无限事件循环”使用鼠标位置方法,您可以使用:
class BoardX(tk.Canvas):
__cells=None
__indicators=None
def __init__(self):
tk.Canvas.__init__(self)
self.__cells=[]
self.__indicators=[]
self.bind('<Motion>', self.show_pos)
for row in range(3):
for column in range(3):
ulx, uly = column*cellsize, row*cellsize
lrx, lry = ulx+cellsize, uly+cellsize
self.__cells.append(self.create_rectangle(ulx, uly, lrx, lry,
fill='green', tags="cell"))
self.__indicators.append(self.create_rectangle(ulx+39, uly+20, lrx-1, lry-20,
fill='red',
state='hidden', tags="indicator"))
def show_pos(self, event):
""" Get closest widget or widget that we are above,
tagged "cell" and indicate it
"""
# the loop is needed for not to run into value errors
halo=0
widget = self.find_closest(event.x, event.y, halo=halo)
# edit - avoid loop!
if not widget[0] in self.find_withtag("cell"):
return
index = self.__cells.index(widget[0])
for i in range(len(self.__indicators)):
state='hidden'
if i == index:
state='normal'
self.itemconfig(self.__indicators[i], state=state)
这不会使您的方法中的事件受到约束,因此应该解决您的问题
如果您出于任何原因不想采用这种方法,您只能绑定到输入
并使用查找带标记的指示器(“指示器”)
-方法隐藏其他每个指示器
编辑
已更正代码示例以避免循环。使用鼠标位置方法,您可以使用:
class BoardX(tk.Canvas):
__cells=None
__indicators=None
def __init__(self):
tk.Canvas.__init__(self)
self.__cells=[]
self.__indicators=[]
self.bind('<Motion>', self.show_pos)
for row in range(3):
for column in range(3):
ulx, uly = column*cellsize, row*cellsize
lrx, lry = ulx+cellsize, uly+cellsize
self.__cells.append(self.create_rectangle(ulx, uly, lrx, lry,
fill='green', tags="cell"))
self.__indicators.append(self.create_rectangle(ulx+39, uly+20, lrx-1, lry-20,
fill='red',
state='hidden', tags="indicator"))
def show_pos(self, event):
""" Get closest widget or widget that we are above,
tagged "cell" and indicate it
"""
# the loop is needed for not to run into value errors
halo=0
widget = self.find_closest(event.x, event.y, halo=halo)
# edit - avoid loop!
if not widget[0] in self.find_withtag("cell"):
return
index = self.__cells.index(widget[0])
for i in range(len(self.__indicators)):
state='hidden'
if i == index:
state='normal'
self.itemconfig(self.__indicators[i], state=state)
这不会使您的方法中的事件受到约束,因此应该解决您的问题
如果您出于任何原因不想采用这种方法,您只能绑定到输入
并使用查找带标记的指示器(“指示器”)
-方法隐藏其他每个指示器
编辑
代码示例已更正,以避免循环。由于在状态更改(Tkinter.py,def\u cnfmerge)后调用了“update”,您的状态更改会导致额外的状态更改,这会使您的循环中出现足够快的鼠标。尝试通过鼠标位置计算来实现绑定,而不是使用enter/leave,您应该很好。as“状态更改后将调用“更新”(Tkinter.py,def_cnfmerge)您的状态更改会导致其他状态更改,这会导致循环中足够快地运行鼠标。尝试通过鼠标位置计算而不是进入/离开来实现绑定,您应该很好。谢谢您的回答。根据您之前的简短评论,我使用find_closest进行了处理。我存储了单元格和指示器在一个以相应的bbox值作为键的dict中。“标记”的东西没有出现在我的脑海中。简而言之:我不是很成功。但是你的解决方案——尽管更加优雅——也不起作用。有时在按住鼠标后,它会在while…-循环中无限受阻。我决定使用一个更简单的解决方案并绘制指示器如果鼠标“进入”指示器,则使用背景色和手柄。谢谢您的回答。根据您之前的简短评论,我使用find_Nestest进行了处理。我将单元格和指示器存储在dict中,并将相应的bbox值作为键。我没有想到“标记”的内容。简而言之,我不是很成功。但您的解决方案-非太不雅致了-也不起作用。有时在推鼠标后,它会在while…-循环中无限地阻塞。我决定使用一种更简单的解决方案,在鼠标“进入”指示器时,用背景色和手柄绘制指示器。