如何在Tkinter中使用一个“绑定”绑定多个小部件?

时间:2013-03-12 13:02:15

标签: python widget 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()

我的目标是只有两个绑定(“Enter”和“Leave”事件)而不是上面的六个。

感谢您提出任何想法

2 个答案:

答案 0 :(得分:7)

要回答您关于是否可以将单个绑定应用于多个小部件的具体问题,答案是肯定的。它可能会导致更多的代码而不是更少,但这很容易做到。

所有tkinter小部件都有一个名为“bindtags”的东西。 Bindtags是附加绑定的“标签”列表。你总是在不知情的情况下使用它。绑定到窗口小部件时,绑定实际上不在窗口小部件本身上,而是在与窗口小部件的低级别名称同名的标记上。默认绑定位于与窗口小部件(与基础类,不一定是python类)同名的标记上。当您致电bind_all时,您将绑定到代码"all"

关于bindtags的好处是你可以随意添加和删除标签。因此,您可以添加自己的标记,然后使用bind_class为其分配绑定(我不知道为什么Tkinter作者选择了该名称...)。

要记住的一件重要事情是bindtags有一个订单,事件按此顺序处理。如果事件处理程序返回字符串"break",则在检查任何剩余的绑定标记之前,事件处理将停止。

这样做的实际结果是,如果您希望其他绑定能够覆盖这些新绑定,请将绑定标签添加到最后。如果您希望绑定无法被其他绑定覆盖,请将其置于开头。

实施例

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 Basic Widget Methods页面上。

答案 1 :(得分:6)

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循环的主体,也可以轻松地将所做的操作更改为所有按钮。