如何停止在Tkinter中触发事件?
我有一些代码,像这样:
from Tkinter import *
master = Tk()
def oval_mouse_click(event):
print "in oval"
def canvas_mouse_click(event):
print "in canvas"
w = Canvas(master, width = 800, height = 600)
uid = w.create_oval(390, 290, 410, 310, fill='blue')
w.tag_bind(uid, "<Button-1>", lambda x: oval_mouse_click(x))
w.bind("<Button-1>" , canvas_mouse_click)
w.pack()
mainloop()
当我点击画布(Canvas)时,控制台会显示“在画布内”的信息。
而当我点击椭圆(Oval)时,控制台会显示两条信息:“在椭圆内”和“在画布内”,但我只想看到第一条信息。有没有办法阻止事件的触发呢?
我可以用一个全局标志来解决这个问题,但我觉得对于Tkl来说,应该有更自然的方法。
2 个回答
3
我刚刚在那个类似的问题上发布了一个改进的解决方案,链接在这里:Python tkinter: 停止事件在文本小部件标签中的传播。
这个解决方案的核心思路和之前的方案是一样的:通过将Canvas
小部件绑定到与tag_bind
相同的事件序列上来“劫持”它。我想出的改进方案现在可以模拟Tk的其他绑定+回调对中预期的return "break"
行为。简单来说就是:
- 创建一个包装器,围绕你想要的
callback
,也就是一个可调用的类实例。 - 当这个类实例被调用时,运行
callback
并检查它的结果。- 如果结果是
"break"
,那么暂时劫持事件传播:将Canvas
小部件绑定到与tag_bind
相同的事件上,并设置一个空的回调。然后,在一段空闲时间后,unbind
。 - 如果结果不是
"break"
:什么都不做,事件会自动传播到Canvas
。
- 如果结果是
上面的链接提供了一个完整的示例,使用的是Text
小部件,但这个方法可以直接应用到Canvas小部件上。
2
这里有一个最简单的例子来解决你的问题:
import Tkinter
def oval_mouse_click(event):
print "in oval"
event.widget.tag_click = True
def canvas_mouse_click(event):
if event.widget.tag_click:
event.widget.tag_click = False
return
print "in canvas"
root = Tkinter.Tk()
canvas = Tkinter.Canvas(width=400, height=300)
oid = canvas.create_oval(400/2-10, 300/2-10, 400/2+10, 300/2+10, fill='blue')
canvas.tag_click = False
canvas.tag_bind(oid, "<Button-1>", oval_mouse_click)
canvas.bind("<Button-1>" , canvas_mouse_click)
canvas.pack()
root.mainloop()
在Canvas
中,没有比这个更简单的方法了。