On Wed, Feb 06, 2008 at 01:21:30AM +0100, Gael Varoquaux wrote: > On Tue, Feb 05, 2008 at 07:16:59PM -0500, Paul Kienzle wrote: > > I'll look around some more and see if I can find the sleep until next > > event function in wx. > > Yeah, sleep, I need more of that. Or maybe you can find wx.coffee ?
Sleep not found, despite half the night trying. What follows three experiments I tried, but now I'm out of ideas. The last thing to do would be to follow your suggestion and move the busy loop from ginput to CanvasBase and let the individual backends override with a better solution if available. - Paul Attempted solutions for modal wx event processing: 1. Run a private event loop with a timer every 0.1s to see if the user has done selecting. This works, but it doesn't like it if the window is closed before completion. I didn't test for it, but super-fast clicking should let the user sometimes select an extra point, so not a great solution. def event_loop(self, done=lambda:False, timeout=0): 'run the eventloop until done or timeout' print "Running private event loop" loop = wx.EventLoop() # stop after timeout period def donewaiting(*args,**kw): print "Done waiting" loop.Exit() if timeout > 0: print "Starting timer" outtimer = wx.Timer(self, id=MODAL_TIMEOUT_TIMER) outtimer.Start(timeout*1000, oneShot=True) self.Bind(wx.EVT_TIMER, donewaiting, outtimer) # check if done every 0.1 s def checkdone(*args,**kw): if done(): loop.Exit() steptimer = wx.Timer(self, id=MODAL_STEP_TIMER) steptimer.Start(100, oneShot=False) self.Bind(wx.EVT_TIMER, checkdone, steptimer) loop.Run() steptimer.Stop() return 2. What seems like it should work is to use an event handler which checks after processing each event whether or not this completes the condition and so we can exit the loop. However, ProcessEvent never seems to be called. Reading elsewhere I see that ProcessEvent is not a virtual function in wx, so presumably we can't override it in a subclass of wx.EvtHandler. # Redirect input events to new handler class ModalHandler(wx.EvtHandler): def ProcessEvent(self, evt): print "Processing event" if done(): loop.Exit() return False # True if processed print "Pushing handler" handler = ModalHandler() self.PushEventHandler(handler) print "enabled",handler.GetEvtHandlerEnabled() print "handler->next",handler.GetNextHandler() print "self->previous",self.GetPreviousHandler() loop.Run() self.PopEventHandler(False) print "Done!" 3. Revising two somewhat, I send all events for the canvas through my own event handler. To make sure I see each one I bind each window event to my own dispatcher as well as to the underlying window. I then use this handler rather than self in the canvas __init__. This fails because either the window handler is not called or it is called twice, depending on whether PushEventHandler and ProcessEvent are called. It also fails if the window is closed unexpectedly. class ModalHandler(wx.EvtHandler): def __init__(self, window): print "Creating handler" wx.EvtHandler.__init__(self) self.done = lambda:False window.PushEventHandler(self) self.window = window self.timer = wx.Timer() self.Bind(wx.EVT_TIMER, self.OnTimeout, self.timer) self.loop = wx.EventLoop() def _dispatch(self, evt): """Ick! ProcessEvent is not virtual, so we can't override directly!""" #print "Processing event" self.window.ProcessEvent(evt) if self.done(): self.loop.Exit() print "Returning event" return True def EndModal(self): """Force the loop to exit""" self.done = lambda:True def Bind(self,evt,action,*args,**kw): # Force all events through ProcessEvent. This is the first binding. # ProcessEvent will dispatch the event to the window itself, so be # sure to tell the window what to do with the event. This is the # second binding. if wx.VERSION_STRING >= '2.5': # Event handlers 2.5 print "Binding 2.5" wx.EvtHandler.Bind(self.window,evt,action,*args,**kw) wx.EvtHandler.Bind(self,evt,self._dispatch) else: print "Binding 2.4" evt(self,self.ProcessEvent) evt(self.window,*args,**kw) def OnTimeout(self): print "timeout" self.loop.Exit() def RunLoop(self, done=lambda:False, timeout=0): print "Running loop" self.done = done if timeout > 0: self.timer.Start(timeout, oneShot=True) try: self.loop.Run() finally: self.timer.Stop() self.done = lambda:False ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2008. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ _______________________________________________ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel