5

我对一系列按钮有一个共同的回调。调用回调后,我想通过其先前分配的名称来识别调用者。但我无法在 Tkinter 文档中弄清楚如何做到这一点。有任何想法吗?

我的程序大约是。

def callback(event):
    event.widget['text'] # 'name' does not work so 
                         # I have to use the label of the button now, but it is a dirty solution.

root.bind("<Button-1>", cb_button)

我需要这些名称,因为我使用pytkgen从 JSON 加载 GUI 。

更新:
贾斯汀的解决方案看起来不错,但为什么9不管点击哪个按钮,下面的代码总是打印?

def cb_button(i):
    print i

buttons = [('btn'+str(i), i) for i in range(10)]
for (b, i) in buttons:
    root.button(b, lambda: cb_button(i))
4

3 回答 3

4

小部件的 winfo_name() 方法返回小部件的名称。它通常是一个用字符串表示的 8 位数字,即:'40123211' 如果你有一个事件对象,evt,那么使用:evt.widget.winfo_name()

在问题的正文中,您要问一些不同的问题:“我如何判断哪个按钮调用了通用回调函数”

使用 lambda 函数将唯一值传递给公共回调:

根据对您问题的更新,我想我理解了这个问题。您有一个 JSON 文件,用于通过 pytkgen 创建 Tkinter 接口。在这个 JSON 文件中定义了几个按钮,每个按钮都有一个唯一的名称。在为这些按钮分配命令时,它们都被赋予相同的回调,但回调需要知道哪个按钮发起了呼叫,并且您希望通过名称来做到这一点。那是对的吗?

如果是这样,我猜您当前正在创建这样的回调分配(非常通用的示例,假设这是通过使用 JSON 文件的路径root调用返回的接口根):tkgen.gengui.TkJson

root.button("name1", callback)
root.button("name2", callback)
...

但是,这并没有给你想要的名字。传递名称的一种方法是创建一个lambda将按钮名称传递给回调函数的方法。回调分配将如下所示:

root.button("name1", lambda:callback("name1"))
root.button("name2", lambda:callback("name2"))
...

然后您的回调定义可能如下所示:

def callback(name):
    if name == "name1":
        # Do something in here
    elif name == "name2":
        # Do something else in here
    ...

更新:如果您在循环内创建按钮,则需要修改 lambda 定义以将所需的循环变量存储为关键字默认值。否则循环变量的最终值将应用于所有按钮。

def cb_button(i):
    print i

buttons = [('btn'+str(i), i) for i in range(10)]
for (b, i) in buttons:
    root.button(b, lambda x=i: cb_button(x))

向小部件对象添加属性

另一种解决方案是在回调函数中检查按钮小部件对象的属性。(本例使用 Tkinter)

but1 = Tkinter.Button(root, text="Sync", width=10)
but1.bind("<Button-1>", doButton)
but1.myId = "this"

but2 = Tkinter.Button(root, text="Sync", width=10)
but2.bind("<Button-1>", doButton)
but2.myId = "that"
but2.otherStuff = "anything"

def doButton(evt):
  if evt.widget.myId == "this":
    print("This")
  else:
    print("That "+evt.widget.otherStuff)
于 2013-06-06T23:19:09.510 回答
0

一种常见的方法是使用一个通用函数,但不完全相同的回调(通过lambda闭包,正如贾斯汀的回答所指出的那样)。

依赖于工具包的内部有两种不完美的替代方案:

  • _nametkinter在小部件中提供私有属性
  • pytkgen root 具有一个widgets字典,您可以迭代以找到您的小部件名称 ( name = [k for k, v in root.widgets.iteritems() if v == event.widget][0])。为了更好地分离代码,您可以从小部件中检索根目录event.widget._nametowidget('.')

值得注意的是,这些解决方案不适command用于不为其回调提供事件的按钮。并且优先通过绑定操作来完成按钮, command因为它实现了按钮的通常行为(释放时的操作,您可以通过离开按钮来中止......)。

于 2013-06-07T08:30:17.057 回答
0

我不记得如何获得名称,但您始终可以使用

打印目录(事件)

或者

打印目录(event.widget)

于 2013-06-06T18:15:07.943 回答