passing data to Tkinter call backs

2010-06-09 Thread Nick Keighley
Hi,

If this is the wrong place for Tkinter in python please direct me
elsewhere!

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?

Or am I reduced to using spit global data? A Singleton is just
Global Data by other means.


--
Nick Keighley

This led to packs of feral Global Variables roaming the
address space.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: passing data to Tkinter call backs

2010-06-09 Thread Bruno Desthuilliers

Nick Keighley a écrit :

Hi,

If this is the wrong place for Tkinter in python please direct me
elsewhere!

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:


Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41)
[GCC 4.3.3] on linux2
Type help, copyright, credits or license for more information.
 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 ???



Or am I reduced to using spit global data? A Singleton is just
Global Data by other means.



 from functools import partial
 data = dict()
 def handle_event(event, data):
... data['foo'] = bar
... print event
...
 p = partial(handle_event, data=data)
 p(e)
__main__.Event object at 0xb75383ec
 data
{'foo': 'bar'}


Note that data doesn't have to be global here.

--
http://mail.python.org/mailman/listinfo/python-list


Re: passing data to Tkinter call backs

2010-06-09 Thread Nick Keighley
On 9 June, 10:35, Bruno Desthuilliers bruno.
42.desthuilli...@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

  Or am I reduced to using spit global data? A Singleton is just
  Global Data by other means.

   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 but a little more elegantly?

   p(e)
 __main__.Event object at 0xb75383ec
   data
 {'foo': 'bar'}
  

 Note that data doesn't have to be global here.

# callback for mouse click event
def mouse_clik_event (event, data) :
dosomething (event.x, event.y, data)
draw_stuff (display, data)

data = Data(6.0, 0.2, 0.3)
draw_stuff (display, data)

# snag mouse
display.canvas.bind(ButtonRelease-1, lambda event:
mouse_clik_event (event, mandelbrot))




--
There are known knowns; there are things we know we know.
We also know there are known unknowns; that is to say we
know there are some things we do not know. But there are
also unknown unknowns -- the ones we don't know we don't
know.







-- 
http://mail.python.org/mailman/listinfo/python-list


Re: passing data to Tkinter call backs

2010-06-09 Thread Bruno Desthuilliers

Nick Keighley a écrit :

On 9 June, 10:35, Bruno Desthuilliers bruno.
42.desthuilli...@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 !-)


--
http://mail.python.org/mailman/listinfo/python-list


Re: passing data to Tkinter call backs

2010-06-09 Thread Nick Keighley
On 9 June, 13:50, Bruno Desthuilliers bruno.
42.desthuilli...@websiteburo.invalid wrote:
 Nick Keighley a écrit :





  On 9 June, 10:35, Bruno Desthuilliers bruno.
  42.desthuilli...@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 !-)

I'm somewhat newbie at Python but I'd seen lambda elsewhere (scheme).
I like the closure trick... I'm using Python In a Nutshell as my
guide.



-- 
http://mail.python.org/mailman/listinfo/python-list


Re: passing data to Tkinter call backs

2010-06-09 Thread Bruno Desthuilliers

Nick Keighley a écrit :

On 9 June, 13:50, Bruno Desthuilliers bruno.

(snip)

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 !-)


I'm somewhat newbie at Python but I'd seen lambda elsewhere (scheme).
I like the closure trick... 


Well... Python is not Scheme - specially wrt/ lambdas and closures. 
While it has some restricted support for some FP idioms, Python is 
definitly an OO language.


FWIW, you could implement the functool.partial class using closures / 
HOF (and it's been done before), but it's easier and just more obvious 
to take the OO route here.


--
http://mail.python.org/mailman/listinfo/python-list


Re: passing data to Tkinter call backs

2010-06-09 Thread rantingrick
On Jun 9, 4:23 am, Nick Keighley nick_keighley_nos...@hotmail.com
wrote:

 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?

I don't know how you're triggering redraws but you need to read this
first...

w.update()
This method forces the updating of the display. It should be used only
if you know what you're doing, since it can lead to unpredictable
behavior or looping. It should never be called from an event callback
or a function that is called from an event callback.

w.update_idletasks()
Some tasks in updating the display, such as resizing and redrawing
widgets, are called idle tasks because they are usually deferred until
the application has finished handling events and has gone back to the
main loop to wait for new events.

If you want to force the display to be updated before the application
next idles, call the w.update_idletasks() method on any widget.
-- 
http://mail.python.org/mailman/listinfo/python-list