[Python/Tkinter]如何获取在函数"event_generate"中设置的数据值

9
我正在使用Python 2.7.4,并且对Tkinter不熟悉。我在下面的代码中遇到了问题。 我生成了一个名为“test”的事件,并使用字符串设置了“data”选项,但是从事件中检索它时出现错误。
错误 -> AttributeError:事件实例没有属性“data”
from Tkinter import *

def handle_it(event):
    # print "event handler"
    print event.data

root = Tk()
root.after(1, lambda: root.event_generate('<<test>>', data="hi there"))
root.bind('<<test>>', handle_it)
root.mainloop()

我找不到相关的 Python 文档,所以参考了下面的 Tcl 文档: http://www.tcl.tk/man/tcl8.5/TkCmd/event.htm#M14

Python 2.7 的 TKinter 支持 "data" 选项吗?谢谢!

2个回答

11

很抱歉,它并不支持。Tcl解释器将其识别为有效选项,但它是事件类中未包括的缺失选项之一,例如warp。您可以查看Tkinter源代码的1188行以查看其余缺失选项。


然而,我检查了字段“Tkinter.TkVersion”和“Tkinter.TclVersion”,它们都是8.5。看起来只部分支持一些选项,请参考http://www.tcl.tk/man/tcl8.4/TkCmd/event.htm。很抱歉听到Python目前不支持这些缺失的选项,我在谷歌上搜索到有人已经在python.org上提交了一个问题作为功能请求,希望他们能解决它http://bugs.python.org/issue3405。 - vicd
@vicd 不用谢。有一个补丁,但是它是在2008年发布的。我已经将自己添加到了该问题的关注列表中,所以如果有任何消息,我会告诉你的。 - A. Rodas
2
后来的Python版本中已经支持了吗? - SoleSoul

6

Tkinter无法正确处理event_generate的数据字段。

下面是一个使用Tkinter的私有API(实际上是Tcl...)的片段,可以读取此字段。这个函数只能处理字面量,并且我通常会将数据作为带有字面量的字典传递。

from Tkinter import *

def handle_it(event):
    # print "event handler"
    print event.data

def bind_event_data(widget, sequence, func, add = None):
    def _substitute(*args):
        e = lambda: None #simplest object with __dict__
        e.data = eval(args[0])
        e.widget = widget
        return (e,)

    funcid = widget._register(func, _substitute, needcleanup=1)
    cmd = '{0}if {{"[{1} %d]" == "break"}} break\n'.format('+' if add else '', funcid)
    widget.tk.call('bind', widget._w, sequence, cmd)

root = Tk()

# unfortunately, does not work with my snippet (the data argument is eval-ed)
# you can adapt it to handle raw string.
root.after(100, lambda : root.event_generate('<<test>>', data="hi there"))
# works, but definitely looks too hacky
root.after(100, lambda : root.event_generate('<<test>>', data="'hi there'"))
# the way I typically use it
root.after(100, lambda : root.event_generate('<<test>>', data={"content": "hi there"}))

#should be:
#  root.bind('<<test>>', handle_it)
bind_event_data (root, '<<test>>', handle_it)

root.mainloop()

注意:似乎存在竞态条件,如果延迟太小,事件将无法被捕获。

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