From: <dmk...@us...> - 2008-07-24 10:02:20
|
Revision: 5831 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5831&view=rev Author: dmkaplan Date: 2008-07-24 10:02:13 +0000 (Thu, 24 Jul 2008) Log Message: ----------- Moving "event loop" stuff from blocking_input.py to backends. For backends without a GUI, the default is to throw a NotImplemented error. For backends with a GUI, I have implemented a "start/stop_event_loop_default" that does the default event loop using time.sleep. For WX, I have used the code supplied by Paul Kienzle, but I have been unable to check it because that backend currently doesn't work for me. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/backend_bases.py trunk/matplotlib/lib/matplotlib/backends/backend_cocoaagg.py trunk/matplotlib/lib/matplotlib/backends/backend_fltkagg.py trunk/matplotlib/lib/matplotlib/backends/backend_gtk.py trunk/matplotlib/lib/matplotlib/backends/backend_qt.py trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py trunk/matplotlib/lib/matplotlib/backends/backend_tkagg.py trunk/matplotlib/lib/matplotlib/backends/backend_wx.py trunk/matplotlib/lib/matplotlib/blocking_input.py Modified: trunk/matplotlib/lib/matplotlib/backend_bases.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backend_bases.py 2008-07-24 08:50:43 UTC (rev 5830) +++ trunk/matplotlib/lib/matplotlib/backend_bases.py 2008-07-24 10:02:13 UTC (rev 5831) @@ -23,7 +23,7 @@ """ from __future__ import division -import os, warnings +import os, warnings, time import numpy as np import matplotlib.cbook as cbook @@ -1391,7 +1391,76 @@ """ raise NotImplementedError + def start_event_loop(self,*args,**kwargs): + """ + Start an event loop. This is used to start a blocking event + loop so that interactive functions, such as ginput and + waitforbuttonpress, can wait for events. This should not be + confused with the main GUI event loop, which is always running + and has nothing to do with this. + This is implemented only for backends with GUIs. + """ + raise NotImplementedError + + def stop_event_loop(self,*args,**kwargs): + """ + Stop an event loop. This is used to stop a blocking event + loop so that interactive functions, such as ginput and + waitforbuttonpress, can wait for events. + + This is implemented only for backends with GUIs. + """ + raise NotImplementedError + + def start_event_loop_default(self,timeout=0): + """ + Start an event loop. This is used to start a blocking event + loop so that interactive functions, such as ginput and + waitforbuttonpress, can wait for events. This should not be + confused with the main GUI event loop, which is always running + and has nothing to do with this. + + This function provides default event loop functionality based + on time.sleep that is meant to be used until event loop + functions for each of the GUI backends can be written. As + such, it throws a deprecated warning. + + Call signature:: + + start_event_loop_default(self,timeout=0) + + This call blocks until a callback function triggers + stop_event_loop() or *timeout* is reached. If *timeout* is + <=0, never timeout. + """ + str = "Using default event loop until function specific" + str += " to this GUI is implemented" + warnings.warn(str,DeprecationWarning) + + if timeout <= 0: timeout = np.inf + timestep = 0.01 + counter = 0 + self._looping = True + while self._looping and counter*timestep < timeout: + self.flush_events() + time.sleep(timestep) + counter += 1 + + def stop_event_loop_default(self): + """ + Stop an event loop. This is used to stop a blocking event + loop so that interactive functions, such as ginput and + waitforbuttonpress, can wait for events. + + Call signature:: + + stop_event_loop_default(self) + """ + self._looping = False + + + class FigureManagerBase: """ Helper class for matlab mode, wraps everything up into a neat bundle Modified: trunk/matplotlib/lib/matplotlib/backends/backend_cocoaagg.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_cocoaagg.py 2008-07-24 08:50:43 UTC (rev 5830) +++ trunk/matplotlib/lib/matplotlib/backends/backend_cocoaagg.py 2008-07-24 10:02:13 UTC (rev 5831) @@ -58,6 +58,16 @@ def blit(self, bbox): pass + def start_event_loop(self,*args,**kwargs): + FigureCanvasBase.start_event_loop_default(self,*args,**kwargs) + start_event_loop.__doc__=FigureCanvasBase.start_event_loop_default.__doc__ + + def stop_event_loop(self,*args,**kwargs): + FigureCanvasBase.stop_event_loop_default(self,*args,**kwargs) + stop_event_loop.__doc__=FigureCanvasBase.stop_event_loop_default.__doc__ + + + NibClassBuilder.extractClasses('Matplotlib.nib', mplBundle) class MatplotlibController(NibClassBuilder.AutoBaseClass): Modified: trunk/matplotlib/lib/matplotlib/backends/backend_fltkagg.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_fltkagg.py 2008-07-24 08:50:43 UTC (rev 5830) +++ trunk/matplotlib/lib/matplotlib/backends/backend_fltkagg.py 2008-07-24 10:02:13 UTC (rev 5831) @@ -247,6 +247,14 @@ def widget(self): return self.canvas + def start_event_loop(self,*args,**kwargs): + FigureCanvasBase.start_event_loop_default(self,*args,**kwargs) + start_event_loop.__doc__=FigureCanvasBase.start_event_loop_default.__doc__ + + def stop_event_loop(self,*args,**kwargs): + FigureCanvasBase.stop_event_loop_default(self,*args,**kwargs) + stop_event_loop.__doc__=FigureCanvasBase.stop_event_loop_default.__doc__ + def destroy_figure(ptr,figman): figman.window.hide() Gcf.destroy(figman._num) @@ -491,7 +499,7 @@ default_filetype = base.canvas.get_default_filetype() sorted_filetypes = filetypes.items() sorted_filetypes.sort() - + selected_filter = 0 filters = [] for i, (ext, name) in enumerate(sorted_filetypes): @@ -518,7 +526,7 @@ lastDir = os.path.dirname(fname) file_chooser.directory(lastDir) format = sorted_filetypes[file_chooser.filter_value()][0] - + try: base.canvas.print_figure(fname, format=format) except IOError, msg: Modified: trunk/matplotlib/lib/matplotlib/backends/backend_gtk.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_gtk.py 2008-07-24 08:50:43 UTC (rev 5830) +++ trunk/matplotlib/lib/matplotlib/backends/backend_gtk.py 2008-07-24 10:02:13 UTC (rev 5831) @@ -396,7 +396,14 @@ gtk.gdk.flush() gtk.gdk.threads_leave() + def start_event_loop(self,*args,**kwargs): + FigureCanvasBase.start_event_loop_default(self,*args,**kwargs) + start_event_loop.__doc__=FigureCanvasBase.start_event_loop_default.__doc__ + def stop_event_loop(self,*args,**kwargs): + FigureCanvasBase.stop_event_loop_default(self,*args,**kwargs) + stop_event_loop.__doc__=FigureCanvasBase.stop_event_loop_default.__doc__ + class FigureManagerGTK(FigureManagerBase): """ Public attributes Modified: trunk/matplotlib/lib/matplotlib/backends/backend_qt.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_qt.py 2008-07-24 08:50:43 UTC (rev 5830) +++ trunk/matplotlib/lib/matplotlib/backends/backend_qt.py 2008-07-24 10:02:13 UTC (rev 5831) @@ -177,6 +177,14 @@ def flush_events(self): qt.qApp.processEvents() + def start_event_loop(self,*args,**kwargs): + FigureCanvasBase.start_event_loop_default(self,*args,**kwargs) + start_event_loop.__doc__=FigureCanvasBase.start_event_loop_default.__doc__ + + def stop_event_loop(self,*args,**kwargs): + FigureCanvasBase.stop_event_loop_default(self,*args,**kwargs) + stop_event_loop.__doc__=FigureCanvasBase.stop_event_loop_default.__doc__ + class FigureManagerQT( FigureManagerBase ): """ Public attributes Modified: trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py 2008-07-24 08:50:43 UTC (rev 5830) +++ trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py 2008-07-24 10:02:13 UTC (rev 5831) @@ -181,6 +181,14 @@ def flush_events(self): Qt.qApp.processEvents() + def start_event_loop(self,*args,**kwargs): + FigureCanvasBase.start_event_loop_default(self,*args,**kwargs) + start_event_loop.__doc__=FigureCanvasBase.start_event_loop_default.__doc__ + + def stop_event_loop(self,*args,**kwargs): + FigureCanvasBase.stop_event_loop_default(self,*args,**kwargs) + stop_event_loop.__doc__=FigureCanvasBase.stop_event_loop_default.__doc__ + class FigureManagerQT( FigureManagerBase ): """ Public attributes Modified: trunk/matplotlib/lib/matplotlib/backends/backend_tkagg.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_tkagg.py 2008-07-24 08:50:43 UTC (rev 5830) +++ trunk/matplotlib/lib/matplotlib/backends/backend_tkagg.py 2008-07-24 10:02:13 UTC (rev 5831) @@ -287,6 +287,14 @@ def flush_events(self): self._master.update() + def start_event_loop(self,*args,**kwargs): + FigureCanvasBase.start_event_loop_default(self,*args,**kwargs) + start_event_loop.__doc__=FigureCanvasBase.start_event_loop_default.__doc__ + + def stop_event_loop(self,*args,**kwargs): + FigureCanvasBase.stop_event_loop_default(self,*args,**kwargs) + stop_event_loop.__doc__=FigureCanvasBase.stop_event_loop_default.__doc__ + class FigureManagerTkAgg(FigureManagerBase): """ Public attributes Modified: trunk/matplotlib/lib/matplotlib/backends/backend_wx.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_wx.py 2008-07-24 08:50:43 UTC (rev 5830) +++ trunk/matplotlib/lib/matplotlib/backends/backend_wx.py 2008-07-24 10:02:13 UTC (rev 5831) @@ -1185,7 +1185,57 @@ if figManager is not None: figManager.canvas.draw() + def start_event_loop(self, timeout=0): + """ + Start an event loop. This is used to start a blocking event + loop so that interactive functions, such as ginput and + waitforbuttonpress, can wait for events. This should not be + confused with the main GUI event loop, which is always running + and has nothing to do with this. + Call signature:: + + start_event_loop(self,timeout=0) + + This call blocks until a callback function triggers + stop_event_loop() or *timeout* is reached. If *timeout* is + <=0, never timeout. + """ + root = self.GetTopLevelParent() + bind(root, wx.EVT_CLOSE, self.stop_event_loop) + + id = wx.NewId() + timer = wx.Timer(self, id=id) + if timeout > 0: + timer.Start(timeout*1000, oneShot=True) + bind(self, wx.EVT_TIMER, self.stop_event_loop, id=id) + self._event_loop.Run() + timer.Stop() + + def stop_event_loop(self, event=None): + """ + Stop an event loop. This is used to stop a blocking event + loop so that interactive functions, such as ginput and + waitforbuttonpress, can wait for events. + + Call signature:: + + stop_event_loop_default(self) + """ + if self._event_loop.IsRunning(): + self._event_loop.Exit() + +# Event binding code changed after version 2.5 +if wx.VERSION_STRING >= '2.5': + def bind(actor,event,action,**kw): + actor.Bind(event,action,**kw) +else: + def bind(actor,event,action,id=None): + if id is not None: + event(actor, id, action) + else: + event(actor,action) + def show(): """ Current implementation assumes that matplotlib is executed in a PyCrust Modified: trunk/matplotlib/lib/matplotlib/blocking_input.py =================================================================== --- trunk/matplotlib/lib/matplotlib/blocking_input.py 2008-07-24 08:50:43 UTC (rev 5830) +++ trunk/matplotlib/lib/matplotlib/blocking_input.py 2008-07-24 10:02:13 UTC (rev 5831) @@ -50,7 +50,7 @@ # Check if we have enough events already if len(self.events) >= self.n and self.n > 0: - self.done = True + self.fig.canvas.stop_event_loop() def post_event(self): """For baseclass, do nothing but collect events""" @@ -90,7 +90,6 @@ self.n = n self.events = [] - self.done = False self.callbacks = [] # Ensure that the figure is shown @@ -101,17 +100,8 @@ self.callbacks.append( self.fig.canvas.mpl_connect(n, self.on_event) ) try: - # wait for n clicks - counter = 0 - while not self.done: - self.fig.canvas.flush_events() - time.sleep(0.01) - - # check for a timeout - counter += 1 - if timeout > 0 and counter > timeout/0.01: - print "Timeout reached"; - break; + # Start event loop + self.fig.canvas.start_event_loop(timeout=timeout) finally: # Run even on exception like ctrl-c # Disconnect the callbacks self.cleanup() @@ -175,7 +165,7 @@ # consistent with matlab and sometimes quite useful, but will # require the user to test how many points were actually # returned before using data. - self.done = True + self.fig.canvas.stop_event_loop() def button3( self, event ): """ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |