7

我想知道如何用一个“绑定”绑定多个小部件。

例如:

我有三个按钮,我想在悬停后更改它们的颜色。

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”事件)而不是上面的六个。

谢谢你的任何想法

4

2 回答 2

9

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

All tkinter widgets have something called "bindtags". Bindtags are a list of "tags" to which bindings are attached. 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). And when you call bind_all, you're binding to the tag "all".

The great thing about bindtags is that you can add and remove tags all you want. 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...).

An important thing to remember is that bindtags have an order, and events are handled in this order. If an event handler returns the string "break", event handling stops before any remaining bindtags have been checked for bindings.

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

Also, the bindtags method itself is documented on the effbot Basic Widget Methods page among other places.

于 2013-03-12T13:55:18.877 回答
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通过更改循环体也很容易更改对所有按钮的操作。

于 2013-03-12T13:05:26.103 回答