如何在Tkinter中用一个"bind"绑定多个组件?
我想知道怎么用一个“绑定”来绑定多个小部件。
比如说:
我有三个按钮,我想在鼠标悬停时改变它们的颜色。
from Tkinter import *
def SetColor(event):
event.widget.config(bg="red")
return
def ReturnColor(event):
event.widget.config(bg="white")
return
root = Tk()
B1 = Button(root,text="Button 1", bg="white")
B1.pack()
B2 = Button(root, text="Button2", bg="white")
B2.pack()
B3 = Button(root, text= "Button 3", bg="white")
B3.pack()
B1.bind("<Enter>",SetColor)
B2.bind("<Enter>",SetColor)
B3.bind("<Enter>",SetColor)
B1.bind("<Leave>",ReturnColor)
B2.bind("<Leave>",ReturnColor)
B3.bind("<Leave>",ReturnColor)
root.mainloop()
我的目标是只用两个绑定(一个是“进入”,一个是“离开”事件),而不是像上面那样需要六个。
谢谢大家的建议!
2 个回答
关于你问的一个绑定是否可以应用于多个小部件,答案是可以的。这样做可能会导致代码行数增加,但其实很简单。
所有的tkinter小部件都有一个叫“bindtags”的东西。bindtags是一个“标签”的列表,绑定就是附加在这些标签上的。你在使用时其实一直在用这个,只是你可能没注意到。当你给一个小部件绑定事件时,绑定并不是直接在这个小部件上,而是绑定在一个和小部件底层名称相同的标签上。默认的绑定是在一个和小部件类名相同的标签上(这里的类是指底层类,而不一定是python类)。而当你调用bind_all
时,你实际上是在绑定到标签"all"
。
bindtags的一个好处是,你可以随意添加和删除标签。所以,你可以添加自己的标签,然后用bind_class
把绑定分配给它(我也不知道为什么tkinter的作者选择这个名字……)。
需要记住的一点是,bindtags是有顺序的,事件是按照这个顺序来处理的。如果一个事件处理函数返回字符串"break"
,那么事件处理会在检查完剩下的bindtags之前就停止了。
这意味着,如果你想让其他绑定能够覆盖你新的绑定,就把你的bindtag放在最后。如果你希望你的绑定无法被其他绑定覆盖,就把它放在最前面。
示例
import Tkinter as tk
class Example(tk.Frame):
def __init__(self, *args, **kwargs):
tk.Frame.__init__(self, *args, **kwargs)
# add bindings to a new tag that we're going to be using
self.bind_class("mytag", "<Enter>", self.on_enter)
self.bind_class("mytag", "<Leave>", self.on_leave)
# create some widgets and give them this tag
for i in range(5):
l = tk.Label(self, text="Button #%s" % i, background="white")
l.pack(side="top")
new_tags = l.bindtags() + ("mytag",)
l.bindtags(new_tags)
def on_enter(self, event):
event.widget.configure(background="bisque")
def on_leave(self, event):
event.widget.configure(background="white")
if __name__ == "__main__":
root = tk.Tk()
view = Example()
view.pack(side="top", fill="both", expand=True)
root.mainloop()
关于bindtags的更多信息可以在这个回答中找到:https://stackoverflow.com/a/11542200/7432
此外,bindtags
方法本身的文档可以在effbot的基本小部件方法页面以及其他地方找到。
for b in [B1, B2, B3]:
b.bind("<Enter>", SetColor)
b.bind("<Leave>", ReturnColor)
你可以进一步简化你的代码片段:
for s in ["button 1", "button 2", "button 3"]:
b=Button(root, text=s, bg="white")
b.pack()
b.bind("<Enter>", SetColor)
b.bind("<Leave>", ReturnColor)
现在添加额外的按钮变得很简单(只需要在输入列表中再加一个项)。而且,如果你想改变所有按钮的操作,只需修改for
循环的内容就可以了。