passing data to Tkinter call backs

Bruno Desthuilliers bruno.42.desthuilliers at websiteburo.invalid
Wed Jun 9 08:50:08 EDT 2010


Nick Keighley a écrit :
> On 9 June, 10:35, Bruno Desthuilliers <bruno.
> 42.desthuilli... at websiteburo.invalid> wrote:
>> Nick Keighley a crit :
> 
>>> I'm trapping mouse clicks using
>>> canvas.bind("<ButtonRelease-1>", mouse_clik_event)
>>> def mouse_clik_event (event) :
>>>      stuff
>>> What mouse_clik_event does is modify some data and trigger a redraw.
>>> Is there any way to pass data to the callback function? Some GUIs give
>>> you a user-data field in the event, does Tkinter?
>> Never used TkInter much, but if event is a regular Python object, you
>> don't need any "user-data field" - just set whatever attribute you want, ie:
> [...]
>>  >>> class Event(object): pass
>> ...
>>  >>> e = Event()
>>  >>> e.user_data = "here are my data"
>>  >>> e.user_data
>> 'here are my data'
>>  >>>
>>
>> But I fail to see how this would solve your problem here - where would
>> you set this attribute ???
> 
> Those other GUIs also give you a mechanism to pass the data. Say
> another parameter in the bind call

Ok, so my suggestion should work, as well as any equivalent (lambda, 
closure, custom callable object etc).

>>  >>> from functools import partial
>>  >>> data = dict()
>>  >>> def handle_event(event, data):
>> ...     data['foo'] = "bar"
>> ...     print event
>> ...
>>  >>> p = partial(handle_event, data=data)
> 
> ah! the first time I read this I didn't get this. But in the mean time
> cobbled something together using lambda. Is "partial" doing the same
> thing 

Mostly, yes - in both cases you get a callable object that keeps a 
reference on the data. You could also use a closure:

def make_handler(func, data):
    def handler(event):
        func(event, data)
    return handler

def mouse_clik_event (event, data) :
     dosomething (event.x, event.y, data)
     draw_stuff (display, data)

display.canvas.bind(
   "<ButtonRelease-1>",
    make_handler(mouse_click_event, data)
   )

> but a little more elegantly?

Depending on your own definition for "elegantly"...

Note that the lambda trick you used is very idiomatic - functool.partial 
being newer and probably not as used - so one could argue that the most 
common way is also the most "elegant" !-)




More information about the Python-list mailing list