I'm using Python 2.7.4 and new to Tkinter, and I'm stuck with the following code. I generated an event "test" and set the "data" option with a string, but an error occurred when retrieving it from event.
Error -> AttributeError: Event instance has no attribute '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()
I can't find the related Python docs for this case, so I referred to the tcl document as below http://www.tcl.tk/man/tcl8.5/TkCmd/event.htm#M14
Does TKinter of Python 2.7 support "data" option? Thanks!
No, unfortunately it doesn't. The Tcl interpreter recognizes it as a valid option, but it is one of the missing options that are not included in the Event class, like warp
. You can take a look at the line 1188 of the Tkinter source code to see the rest of the missing options.
Tkinter does not handle properly the data field of event_generate.
Here is a snippet using private API of Tkinter (in fact Tcl...) that allows to read this field. This function only works with literals and I usually pass data a dictionary with literals.
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()
Note: there seems to be a race condition that prevent the event to be catched with a too small delay in after.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With