The basic idea in binding an event to a handler is to have the program do something useful in response to an user’s action, e.g.:
self.button.Bind(wx.EVT_BUTTON, self OnButtonPushed)
def OnButtonPushed(self, event):
event.Skip()
DoSomethingWild
But sometimes it might be necessary to DoSomethingWild even without a direct user’s intervention. The most plain solution is to separate the event handler from the method, e.g.
*def OnButtonPushed(self, event):
event.Skip()
self.DoSomethingWild()
def DoSomethingWild(self):
print “Hoo, Hoo, Hoo!”*This snippet works , but can’t be reused, and lenghtens the code. And here it is useful to be able to manually trigger the event. Mike Driscoll suggested to use wx.PostEvent but, try as I could, I was not able to implement it. to the instruction
wx.PostEvent(self.button, wx.PyEvent(wx.EVT_BUTTON)
the compiler replied always
*TypeError: in method ‘PostEvent’, expected argument 2 of type ‘wxEvent &’*that for me is of little use, because I am not able to build a wx.Event &.
My solution, so far, has been the following:
*def SendEvent(window, PyEventBinder):
# Example of PyEventBinder: wx.EVT_BUTTON
# window is the window (control) that triggers the event
cmd = wx.CommandEvent(PyEventBinder.evtType[0])
cmd.SetEventObject(window)
cmd.SetId(window.GetId())
window.GetEventHandler().ProcessEvent(cmd)*Put in a re-usable module, this one also works, as long as the event is a simple one. In fact, there are not so many ways to push a button. But how is it possible to trigger a more complex event, such as a wx.KeyEvent, for example? In other words, how to pass meaningful parameters to SendEvent?
Raffaello,
The basic idea in binding an event to a handler is to have the program do something useful in response to an user's action, e.g.:
/ self.button.Bind(wx.EVT_BUTTON, self OnButtonPushed)
def OnButtonPushed(self, event):
event.Skip()
DoSomethingWild/But sometimes it might be necessary to DoSomethingWild even without a direct user's intervention. The most plain solution is to separate the event handler from the method, e.g.
/ def OnButtonPushed(self, event):
event.Skip()
self.DoSomethingWild()def DoSomethingWild(self):
print "Hoo, Hoo, Hoo!"/This snippet works , but can't be reused, and lenghtens the code. And here it is useful to be able to manually trigger the event. Mike Driscoll suggested to use wx.PostEvent but, try as I could, I was not able to implement it. to the instruction
/wx.PostEvent(self.button, wx.PyEvent(wx.EVT_BUTTON)/
the compiler replied always
/ TypeError: in method 'PostEvent', expected argument 2 of type 'wxEvent &'
/that for me is of little use, because I am not able to build a wx.Event &.
My solution, so far, has been the following:/def SendEvent(window, PyEventBinder):
# Example of PyEventBinder: wx.EVT_BUTTON
# window is the window (control) that triggers the event
cmd = wx.CommandEvent(PyEventBinder.evtType[0])
cmd.SetEventObject(window)
cmd.SetId(window.GetId())
window.GetEventHandler().ProcessEvent(cmd)/Put in a re-usable module, this one also works, as long as the event is a simple one. In fact, there are not so many ways to push a button. But how is it possible to trigger a more complex event, such as a wx.KeyEvent, for example? In other words, how to pass meaningful parameters to SendEvent?/
/
To be honest, I've only read about wx.PostEvent and the ideas behind it. However, I figured since I had suggested it, I had better try and figure it out. It seems that PostEvent is usually used in conjunction with a custom event created by the developer or as an alternative to wx.CallAfter as it is supposedly Thread Safe. I was unable to find a working example of using a pre-existing wx event. Hopefully Robin will be willing to comment on that.
In the mean time, you can look over my silly demo code for PostEvents:
<code>
import wx
import wx.lib.newevent
myNewEvent, EVT_DEMO_EVENT = wx.lib.newevent.NewEvent()
class MyForm(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, 'My Frame')
self.panel = wx.Panel(self, wx.ID_ANY)
myBtn = wx.Button(self.panel, wx.ID_ANY, 'Push Me')
self.Bind(wx.EVT_BUTTON, self.onPush, myBtn)
self.panel.Bind(EVT_DEMO_EVENT, self.onCustomEvtHandler)
def onPush(self, event):
print 'running onPush event handler...'
evt = myNewEvent(attr1="test", attr2=233)
wx.PostEvent(self.panel, evt)
def onCustomEvtHandler(self, event):
print 'You programmatically called your new event!'
if __name__ == '__main__':
app = wx.PySimpleApp()
frame = MyForm().Show()
app.MainLoop()
</code>
I also found a few more links for you. The first one was what I modeled my demo code on.
http://wiki.wxpython.org/CustomEventClasses
http://mail.python.org/pipermail/python-list/2007-July/449872.html
http://osdir.com/ml/gnu.radio.general/2005-02/msg00333.html
I hope that clears it up a little. It helped me anyway. Sorry if all I did was muddle things up.
···
-------------------
Mike Driscoll
Blog: http://blog.pythonlibrary.org
Python Extension Building Network: http://www.pythonlibrary.org
The most plain solution is to separate the event handler from the method, e.g.
/ def OnButtonPushed(self, event):
event.Skip()
self.DoSomethingWild()def DoSomethingWild(self):
print "Hoo, Hoo, Hoo!"/This snippet works , but can't be reused,
why not?
and lenghtens the code.
yes. I often use this pattern:
def OnButtonPushed(self, event=None):
print "Hoo, Hoo, Hoo!"
then it can be called both with and without an event. If you really need the event.Skip() (I rarely do):
def OnButtonPushed(self, event=None):
if event is not None:
event.skip()
print "Hoo, Hoo, Hoo!"
here it is useful to be able to manually trigger the event.
Well, maybe -- I think it's pretty rare that you want to simulate a button push, while it is very common to have multiple ways to trigger the same action: both a button and a menu, or as the result of some other internal action, etc, etc. In fact, I believe strongly that separation of GUI and "working code" is a good idea, so it is a good idea to have non-gui ways to call DoSomethingWild(). Tests, if nothing else.
I don't know the details of your use case, but I'm suggesting that you may be making things hard for little gain.
I'll also note that as wx wraps the native widgets, there are some things that you can't simulate anyway -- at least not without delving in to platform-native APIs
-Chris
···
--
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
I haven’t been deep into wxPython for very long, but the named parameter with the default value of None was the most obvious solution to me when I had some code that needed to be called both with and without an event.
···
On Mon, Jun 16, 2008 at 10:37 AM, Mike Rooney mxr@qvii.com wrote:
Christopher Barker wrote:
yes. I often use this pattern:
def OnButtonPushed(self, event=None):
print "Hoo, Hoo, Hoo!"
then it can be called both with and without an event. If you really need the event.Skip() (I rarely do):
def OnButtonPushed(self, event=None):
if event is not None: event.skip() print "Hoo, Hoo, Hoo!"
Yes, this is exactly the technique I find myself using a lot as well! Often the OnButtonPushed-like method is a Controller method (in MVC) and I want it to be accessible from a scripting environment, a shell, or like you say another GUI element, so this works well to handle it all pretty simply.
If there are any criticisms of this method please let me know, in case we are doing something improperly!
- Mike
wxpython-users mailing list
–
Stand Fast,
tjg.
Christopher’s idea (to allow the argument event to be also equivalent to None) is shorter and less cumbersome than mine, so to be adopted whenever it might be useful to simulate a simple event, like pushing a button. But what about a more complex one?
This debate started with Jesse Aldridge asking whether it is possible to manually construct and send a KeyEvent to a widget for unit testing purposes. And a KeyEvent entails a lot more parameters than a unary True. So, what can we do in this case? Do we subclass the KeyEvent and use wx.PostEvent? or is there a simpler way?
···
2008/6/16 Timothy Grant timothy.grant@gmail.com:
On Mon, Jun 16, 2008 at 10:37 AM, Mike Rooney mxr@qvii.com wrote:
Christopher Barker wrote:
yes. I often use this pattern:
def OnButtonPushed(self, event=None):
print "Hoo, Hoo, Hoo!"
then it can be called both with and without an event. If you really need the event.Skip() (I rarely do):
def OnButtonPushed(self, event=None):
if event is not None: event.skip() print "Hoo, Hoo, Hoo!"
Yes, this is exactly the technique I find myself using a lot as well! Often the OnButtonPushed-like method is a Controller method (in MVC) and I want it to be accessible from a scripting environment, a shell, or like you say another GUI element, so this works well to handle it all pretty simply.
If there are any criticisms of this method please let me know, in case we are doing something improperly!
- Mike
wxpython-users mailing list
I haven’t been deep into wxPython for very long, but the named parameter with the default value of None was the most obvious solution to me when I had some code that needed to be called both with and without an event.
–
Stand Fast,
tjg.
wxpython-users mailing list