Event Handlers in other Modules

Is it possible to bind to a method in a different class?

Eg for a button it would normally be something like

button.Bind(wx.EVT_BUTTON, self.ButtonClick)

and self and event are passed to the ButtonClick method in the current
class.

However, if I do something like

button.Bind(wx.EVT_BUTTON, othermodule.ButtonClick)

then only the event is passed to the ButtonClick method. Is there
anyway to get the self object passed as well

What I'm trying to do is put screen handling code into individual
classes, separate to the class that displays the buttons and text
boxes etc.

The way I usually do something like this is with a mix-in class:

class MyEventHandlerMixin (object) :
  def OnClick (self, event) :
    self.do_something()

class MyWindow (wx.Frame, MyEventHandlerMixin) :
  def __init__ (self, *args, **kwds) :
    # set up window
    button.Bind(wx.EVT_BUTTON, self.OnClick, button)

Keeps the code nice and separate, but in the end the window and the
event handler are one and the same. The other way I can think of
would be to use lambda functions:

button.Bind(wx.EVT_BUTTON, lambda evt: othermodule.OnButtonClick(self,
event), button)

This can easily turn into spaghetti code if not done carefully,
however - especially if your even handler object is processing events
for multiple windows.

-Nat

···

On Wed, Nov 16, 2011 at 3:14 PM, Newt <newt_e@blueyonder.co.uk> wrote:

However, if I do something like

button.Bind(wx.EVT_BUTTON, othermodule.ButtonClick)

then only the event is passed to the ButtonClick method. Is there
anyway to get the self object passed as well

What I'm trying to do is put screen handling code into individual
classes, separate to the class that displays the buttons and text
boxes etc.

This isn't really a wx issue -- wx is passing the event object -- self is coming in because the method is a bound method in a class.

So maybe thinking about it a bit differently would help:

What does you handler need to do its job? If it really needs "self" a lot, then it probably should be method of that class. (see Nat's mixin suggestions)

If, however, you really don't want to put it in that class, then you need a reference to the class somehow -- using the "lambda trick" is one nice way. You can also use functools. here's a nice page describing some options:

http://wiki.wxpython.org/Passing%20Arguments%20to%20Callbacks

But another option is to have your callback know about the class instnace in some other way altogether -- pass it in on __init___, etc. That would be particularly easy if your instance is essentially a singleton (i.e. there is on lone mane Frame, etc)

HTH, Chris

···

On 11/16/11 3:21 PM, Nat Echols wrote:

On Wed, Nov 16, 2011 at 3:14 PM, Newt<newt_e@blueyonder.co.uk> wrote:

However, if I do something like

button.Bind(wx.EVT_BUTTON, othermodule.ButtonClick)

then only the event is passed to the ButtonClick method. Is there
anyway to get the self object passed as well

--
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

Thanks for the responses.

I'll have a think about the lambda functions, but first I'll have a
think about whether splitting the code into separate classes is really
the right thing to do...

Cheers N.

Newt wrote:

Is it possible to bind to a method in a different class?

Eg for a button it would normally be something like

button.Bind(wx.EVT_BUTTON, self.ButtonClick)

and self and event are passed to the ButtonClick method in the current
class.

However, if I do something like

button.Bind(wx.EVT_BUTTON, othermodule.ButtonClick)

then only the event is passed to the ButtonClick method. Is there
anyway to get the self object passed as well

You have an interesting confusion of "module", "class", and "object"
here, and that may be the root of your problem.

"self" is an object -- an instance of a class. If "othermodule" is also
an object, then its ButtonClick will correctly be passed the object and
the event. However, if "othermodule" is a class, the syntax is still
valid, but there isn't any "self" for it to pass, and you should get an
"unbound method" error.

···

--
Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.

What I'm trying to do is put screen handling code into individual
classes, separate to the class that displays the buttons and text
boxes etc

If you are not talking about seperating "UI" (emphasize the I for
interface) from "View" (as in some streaming image) but instead you
are talking about having a window and its controls visually laid out
seperatate from what data data is displayed IN those widgets then here
is an example of seperating Event handler from UI layout.
http://wiki.wxpython.org/PushEventHandler

Recently the MVC pattern was revisited in this user/news/group which
showed even better examples of seperating "concerns". You might also
want to google for the common uses of wx.EvtHandler/wx.Frame...
PushEventHandler, Get/SetPreviousHandler, Get/SetNextHandler methods.