如何在事件中获取小部件名称?

9
from tkinter import *

main = Tk()

def flipper(event):
    # I'd like to do this:
    #if widgetname == switcher:
        #do stuff
    #if widgetname == switcher1:
        #do stuff
    return

switcher = Label(main, bg='white', text="click here", font="-weight bold")
switcher.grid()
switcher.bind("<Button-1>", flipper)


switcher1 = Label(main, bg='white', text="click here", font="-weight bold")
switcher1.grid()
switcher1.bind("<Button-1>", flipper)

switcher2 = Label(main, bg='white', text="click here", font="-weight bold")
switcher2.grid()
switcher2.bind("<Button-1>", flipper)

switcher3 = Label(main, bg='white', text="click here", font="-weight bold")
switcher3.grid()
switcher3.bind("<Button-1>", flipper)

switcher4 = Label(main, bg='white', text="click here", font="-weight bold")
switcher4.grid()
switcher4.bind("<Button-1>", flipper)

switcher5 = Label(main, bg='white', text="click here", font="-weight bold")
switcher5.grid()
switcher5.bind("<Button-1>", flipper)


main.mainloop()

在我的事件函数中,我希望根据所点击的标签执行不同的操作。但我困惑的是,我只能获取所点击的小部件的标识符号,而无法获取其名称。如果我能够获取所有小部件的标识符,则可以执行以下操作:

def flipper(event):
    if event.widget == switcher.identifier():
           do stuff

但是我找不到如何获取特定小部件的ID...

通过其标识符(event.widget()),如何获取小部件的名称?

或者,如何获取指定小部件名称的标识符?

如果两者都不可能,那么我就必须为每个标签制作不同的功能和绑定,这是很多工作,希望不必要。


编辑:

from tkinter import *

main = Tk()

def flipper(event, switch):
    if switch.widget == 's1':
        print("got it")

switcher = Label(main, bg='white', text="click here", font="-weight bold")
switcher.grid()
switcher.bind("<Button-1>", flipper)
switcher.widget = 's1'


main.mainloop()
5个回答

24

获取小部件分配的变量名称没有什么用处,因为一个小部件可能会被分配给多个变量或者根本没有被分配给任何变量。

获取标签文本

您可以访问实际小部件,并使用它来获取标签上的文本。您的示例显示所有标签都相同,因此这可能对您没有用:

def flipper(event):
    print("label text:", event.widget.cget("text"))

使用自定义小部件名称

您还可以给小部件命名。虽然您无法精确获取该名称,但可以非常接近。例如,如果您像这样创建一个标签:

switcher = Label(main, name="switcher", bg='white', text="click here", font="-weight bold")
您可以通过在“.”上进行拆分并取最后一个值来获取小部件的字符串表示形式:
def flipper(event):
    print("widget name:", str(event.widget).split(".")[-1])

通过绑定传递名称

最后,您可以设置绑定以便名称发送到函数:

switcher.bind("<Button-1>", lambda event: flipper(event, "switcher"))
switcher1.bind("<Button-1>", lambda event: flipper(event, "switcher1"))

通过绑定传递名称似乎是我想要做的最可靠的方法。这回答了我的问题,还解决了其他问题。谢谢。 - sidnical
我能否实际使用类似 if event.widget == '.!canvas.!button': 这样的语句呢?因为尽管我打印出了 event.widget 并且它是 .!canvas.!button,但 if 语句并没有被执行。你有什么想法吗? - Delrius Euphoria
2
@CoolCloud:不,但你可以使用 if str(event.widget) == ".!canvas.!button" 但我从来没有发现它有用过。 - Bryan Oakley
哦,好的,我找到了一个解决方法。这是针对这个问题的,不管怎样,我太蠢了,没有想到两者的class是不同的。 - Delrius Euphoria

7
您可以使用event.widget从单击的小部件获取标准参数。
例如:
import tkinter as tk

def callback(event):
    print(event.widget['text'])

main = tk.Tk()

switcher = tk.Label(main, text="click here")
switcher.grid()
switcher.bind("<Button-1>", callback)

main.mainloop()

你可以给小部件分配自己的变量。
switcher.extra = "Hello"

然后获取它。
event.widget.extra

例子:

import tkinter as tk

def callback(event):
    print(event.widget['text'])
    print(event.widget.extra)

main = tk.Tk()

switcher = tk.Label(main, text="click here")
switcher.grid()
switcher.bind("<Button-1>", callback)
switcher.extra = "Hello"

main.mainloop()

您可以使用 lambda 将函数与参数绑定

bind("<Button-1>", lambda event:callback(event, "Hello"))

例子:

import tkinter as tk

def callback(event, extra):
    print(event.widget['text'])
    print(extra)

main = tk.Tk()

switcher = tk.Label(main, text="click here")
switcher.grid()
switcher.bind("<Button-1>", lambda event:callback(event, "Hello"))

main.mainloop()

2
我遇到了同样的问题,我发现使用bind方法是一种简单的方法。 显然,name属性是私有的,但可以通过_name访问。 如果您计划在运行时动态生成小部件,则这非常有用。
# Import Module
from tkinter import *
 
# create root window
root = Tk()
 
# root window title and dimension
root.title("Welcome to Test window")
# Set geometry (widthxheight)
root.geometry('350x200')

#adding a label to the root window
lbl = Label(root, text = "Press a button")
lbl.grid()

#define mouse up event
def mous_up(ev:Event):
    #get calling widget from event
    sender:Button = ev.widget
    
    #set label text
    lbl.configure(text = sender._name + "  up")
    
    #read foreground color from button 
    #If red make green, else make red
    if sender.cget('fg') == "red":
        #normal color
        sender.configure(fg='lime')
        #mouse over color
        sender.configure(activeforeground='green')
    else:
        #normal color
        sender.configure(fg="red")
        #mouse over color
        sender.configure(activeforeground='darkred')

#define mouse down event
def mous_down(ev:Event):
    lbl.configure(text = str(ev.widget._name) + " down")
 
# button widget with red color text
# inside
btn = Button(root, text = "Click me" ,
             fg = "red",name = "button-A")

#bind mouse up and mouse down events
btn.bind('<ButtonRelease-1>',mous_up)
btn.bind('<Button-1>',mous_down)

# set Button grid
btn.grid(column=0, row=1)

#Create another button
btn =  Button(root, text = "Click me2" ,
             fg = "red",name="button2")

#bind mouse up and mouse down events
btn.bind('<ButtonRelease-1>',mous_up)
btn.bind('<Button-1>',mous_down)

#absolute placement of button instead of 
#using grid system
btn.place(x=50,y=100)
 
# all widgets will be here
# Execute Tkinter
root.mainloop()

1

我知道这是一个旧帖子,但我遇到了同样的问题,我想分享一个解决方案,以防有人感兴趣。您可以通过创建小部件的子类来为其命名。例如,“Button”是一个小部件。您可以创建一个继承自button的子小部件“MyButton”,然后向其中添加实例变量(例如名称、唯一ID等)

以下是代码片段

class MyButton(Button):
    def __init__(self, master = None, textVal = "", wName = ""):
        Button.__init__(self, master, text =  textVal)
        self.widgetID = wName #unique identifier for each button. 

当您想要创建一个新的按钮小部件时,请使用 b = MyButton(.....),而不是 b = Button(.......)

这样,您就拥有了所有按钮的功能,以及独特的标识符。


-1
简单粗暴 - 你可以让函数检查一个开关属性。
def flipper(event, switch):
    if switch.widget == 's1':
        do_stuff
        return stuff
    if switch.widget == 's2':
        do_stuff
        return stuff

switcher1.widget = 's1'
switcher2.widget = 's2'

我遇到了一个错误,因为它要求我传递一个开关参数。我已经将我所做的更改添加到了我的原始问题中。 - sidnical
尝试从翻转器参数中移除事件,只保留开关。 - user4322543
我现在得到了一个值,但它与event.widget相同,只是一个标识符号码。这意味着“如果switch.widget == 's1'将始终为false,因为switch.widget是一个随机十进制数。” - sidnical

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接