简体   繁体   English

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

[英]How to bind multiple widgets with one “bind” in Tkinter?

I am wondering how to bind multiple widgets with one "bind". 我想知道如何用一个“绑定”绑定多个小部件。

For expample: 例如:

I have three buttons and I want to change their color after hovering. 我有三个按钮,我想在悬停后改变它们的颜色。

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()

And my goal is to have only two binds (for "Enter" and "Leave" events) instead of six as above. 我的目标是只有两个绑定(用于“Enter”和“Leave”事件)而不是上面的六个。

Thank you for any ideas 谢谢你的任何想法

To answer your specific question on whether you can have a single binding apply to multiple widgets, the answer is yes. 要回答关于是否可以将单个绑定应用于多个小部件的具体问题,答案是肯定的。 It will probably result in more lines of code rather than less, but it's easy to do. 它可能会产生更多的代码而不是更少,但它很容易做到。

All tkinter widgets have something called "bindtags". 所有tkinter小部件都有一个叫做“bindtags”的东西。 Bindtags are a list of "tags" to which bindings are attached. Bindtags是附加绑定的“标签”列表。 You use this all the time without knowing it. 你总是在不知情的情况下使用它。 When you bind to a widget, the binding isn't actually on the widget per se, but on a tag that has the same name as the widget's low level name. 绑定到窗口小部件时,绑定实际上不在窗口小部件本身上,而是在与窗口小部件的低级别名称同名的标记上。 The default bindings are on a tag that is the same name as the widget class (the underlying class, not necessarily the python class). 默认绑定位于与窗口小部件(与基础类,不一定是python类)同名的标记上。 And when you call bind_all , you're binding to the tag "all" . 当你调用bind_all ,你绑定到标签"all"

The great thing about bindtags is that you can add and remove tags all you want. 关于bindtags的好处是你可以随意添加和删除标签。 So, you can add your own tag, and then assign the binding to it with bind_class (I don't know why the Tkinter authors chose that name...). 因此,您可以添加自己的标记,然后使用bind_class为其分配绑定(我不知道为什么Tkinter作者选择了该名称...)。

An important thing to remember is that bindtags have an order, and events are handled in this order. 要记住的一件重要事情是bindtags有一个订单,事件按此顺序处理。 If an event handler returns the string "break" , event handling stops before any remaining bindtags have been checked for bindings. 如果事件处理程序返回字符串"break" ,则在检查任何剩余的bindtags绑定之前,事件处理将停止。

The practical upshot of this is, if you want other bindings to be able to override these new bindings, add your bindtag to the end. 这样做的实际结果是,如果您希望其他绑定能够覆盖这些新绑定,请将绑定标签添加到最后。 If you want your bindings to be impossible to be overridden by other bindings, put it at the start. 如果您希望绑定无法被其他绑定覆盖,请将其置于开头。

Example

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()

A little bit more information about bindtags can be found in this answer: https://stackoverflow.com/a/11542200/7432 有关bindtags的更多信息可以在这个答案中找到: https ://stackoverflow.com/a/11542200/7432

Also, the bindtags method itself is documented on the effbot Basic Widget Methods page among other places. 此外, bindtags方法本身记录在effbot Basic Widget Methods页面中。

for b in [B1, B2, B3]:
    b.bind("<Enter>", SetColor)
    b.bind("<Leave>", ReturnColor)

You could go further and abstract all of your snippet: 您可以进一步抽象所有代码段:

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)

Now it's easy to add extra buttons (just add another entry to the input list). 现在可以轻松添加额外的按钮(只需在输入列表中添加另一个条目)。 It's also easy to change what you do to all the buttons by changing the body of the for loop. 通过更改for循环的主体,也可以轻松地将所做的操作更改为所有按钮。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM