From: <jd...@us...> - 2008-06-24 04:17:24
|
Revision: 5653 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5653&view=rev Author: jdh2358 Date: 2008-06-23 21:17:21 -0700 (Mon, 23 Jun 2008) Log Message: ----------- replaced idle handler with idle event Modified Paths: -------------- trunk/matplotlib/examples/event_handling/idle_and_timeout.py trunk/matplotlib/lib/matplotlib/backend_bases.py trunk/matplotlib/lib/matplotlib/backends/backend_gtk.py trunk/matplotlib/lib/matplotlib/backends/backend_tkagg.py trunk/matplotlib/lib/matplotlib/backends/backend_wx.py trunk/matplotlib/lib/matplotlib/cbook.py Modified: trunk/matplotlib/examples/event_handling/idle_and_timeout.py =================================================================== --- trunk/matplotlib/examples/event_handling/idle_and_timeout.py 2008-06-23 21:39:11 UTC (rev 5652) +++ trunk/matplotlib/examples/event_handling/idle_and_timeout.py 2008-06-24 04:17:21 UTC (rev 5653) @@ -1,31 +1,43 @@ """ Demonstrate/test the idle and timeout API """ +import numpy as np import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_subplot(111) -ax.plot(range(10)) +t = np.arange(0.0, 2.0, 0.01) +y1 = np.sin(2*np.pi*t) +y2 = np.cos(2*np.pi*t) +line1, = ax.plot(y1) +line2, = ax.plot(y2) -def on_idle(canvas): +N = 100 +def on_idle(event): on_idle.count +=1 print 'idle', on_idle.count - if on_idle.count==10: - canvas.mpl_source_remove(on_idle) - return True + line1.set_ydata(np.sin(2*np.pi*t*(N-on_idle.count)/float(N))) + event.canvas.draw() + # test boolean return removal + if on_idle.count==N: + fig.canvas.mpl_disconnect(on_idle.cid) +on_idle.cid = None on_idle.count = 0 def on_timeout(canvas): on_timeout.count +=1 + line2.set_ydata(np.cos(2*np.pi*t*(N-on_idle.count)/float(N))) + line2.figure.canvas.draw() print 'timeout', on_timeout.count - if on_timeout.count==10: - canvas.mpl_source_remove(on_timeout) + # test explicit removal + if on_timeout.count==N: + return False return True on_timeout.count = 0 -fig.canvas.mpl_idle_add(on_idle) -fig.canvas.mpl_timeout_add(100, on_timeout) +on_idle.cid = fig.canvas.mpl_connect('idle_event', on_idle) +#fig.canvas.mpl_timeout_add(100, on_timeout) plt.show() Modified: trunk/matplotlib/lib/matplotlib/backend_bases.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backend_bases.py 2008-06-23 21:39:11 UTC (rev 5652) +++ trunk/matplotlib/lib/matplotlib/backend_bases.py 2008-06-24 04:17:21 UTC (rev 5653) @@ -651,6 +651,12 @@ self.canvas = canvas self.guiEvent = guiEvent +class IdleEvent(Event): + """ + An event triggered by the GUI backend when it is idel -- useful + for passive animation + """ + pass class DrawEvent(Event): """ @@ -869,7 +875,7 @@ A :class:`matplotlib.figure.Figure` instance """ - events = ( + events = [ 'resize_event', 'draw_event', 'key_press_event', @@ -879,7 +885,8 @@ 'scroll_event', 'motion_notify_event', 'pick_event', - ) + 'idle_event', + ] def __init__(self, figure): @@ -1122,6 +1129,13 @@ guiEvent=guiEvent) self.callbacks.process(s, event) + def idle_event(self, guiEvent=None): + 'call when GUI is idle' + s = 'idle_event' + event = IdleEvent(s, self, guiEvent=guiEvent) + self.callbacks.process(s, event) + + def draw(self, *args, **kwargs): """ Render the :class:`~matplotlib.figure.Figure` @@ -1320,8 +1334,11 @@ """ add func to idle handler. The signature of func is:: - func(canvas, *args, **kwargs) + b = func(canvas, *args, **kwargs) + The function will continue to be called until func returns + False or a call to ``canvas.mpl_remove_source(func)`` + use :meth:`mpl_source_remove` to remove func from the idle handler. """ raise NotImplementedError('GUI backend must override') @@ -1331,7 +1348,8 @@ add func to timeout handler; func will be called every millisec. The signature of func is:: - func(canvas, *args, **kwargs) + The function will continue to be called until func returns + False or a call to ``canvas.mpl_remove_source(func)`` use :meth:`mpl_source_remove` to remove func from the timeout handler. """ Modified: trunk/matplotlib/lib/matplotlib/backends/backend_gtk.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_gtk.py 2008-06-23 21:39:11 UTC (rev 5652) +++ trunk/matplotlib/lib/matplotlib/backends/backend_gtk.py 2008-06-24 04:17:21 UTC (rev 5653) @@ -172,8 +172,7 @@ self.set_flags(gtk.CAN_FOCUS) self._renderer_init() - # maps idle/timeout func -> id, remove_func for later removal - self.sourced = dict() + gobject.idle_add(self.idle_event) def scroll_event(self, widget, event): if _debug: print 'FigureCanvasGTK.%s' % fn_name() @@ -397,52 +396,6 @@ gtk.gdk.threads_leave() - def mpl_idle_add(self, func, *args, **kwargs): - """ - add func to idle handler. The signature of func is:: - - func(canvas, *args, **kwargs) - - use :meth:`mpl_source_remove` to remove func from the idle handler. - """ - idle_add = getattr(gobject, 'idle_add', getattr(gtk, 'idle_add')) - remove = getattr(gobject, 'source_remove', getattr(gtk, 'idle_remove')) - - def wrap(): - b = func(self, *args, **kwargs) - return True - - id = idle_add(wrap) - self.sourced[func] = id, remove - - - def mpl_timeout_add(self, millisec, func, *args, **kwargs): - """ - add func to timeout handler; func will be called every - millisec. The signature of func is:: - - func(canvas, *args, **kwargs) - - use :meth:`mpl_source_remove` to remove func from the timeout handler. - """ - timeout_add = getattr(gobject, 'timeout_add', getattr(gtk, 'timeout_add')) - remove = getattr(gobject, 'source_remove', getattr(gtk, 'timeout_remove')) - def wrap(): - b = func(self, *args, **kwargs) - return True - - id = timeout_add(millisec, wrap) - self.sourced[func] = id, remove - - - def mpl_source_remove(self, func): - """ - remove func from idle or timeout handler - """ - id, remove = self.sourced[func] - remove(id) - del self.sourced[func] - class FigureManagerGTK(FigureManagerBase): """ Public attributes Modified: trunk/matplotlib/lib/matplotlib/backends/backend_tkagg.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_tkagg.py 2008-06-23 21:39:11 UTC (rev 5652) +++ trunk/matplotlib/lib/matplotlib/backends/backend_tkagg.py 2008-06-24 04:17:21 UTC (rev 5653) @@ -21,6 +21,8 @@ import matplotlib.windowing as windowing from matplotlib.widgets import SubplotTool +import matplotlib.cbook as cbook + rcParams = matplotlib.rcParams verbose = matplotlib.verbose @@ -38,6 +40,7 @@ cursors.SELECT_REGION: "tcross", } + def round(x): return int(math.floor(x+0.5)) @@ -168,7 +171,17 @@ self._master = master self._tkcanvas.focus_set() + # a dict from func-> cbook.Scheduler threads + self.sourced = dict() + # call the idle handler + def on_idle(*ignore): + self.idle_event() + return True + t = cbook.Idle(on_idle) + + self._tkcanvas.after_idle(lambda *ignore: t.start()) + def resize(self, event): width, height = event.width, event.height if self._resize_callback is not None: @@ -221,6 +234,7 @@ y = self.figure.bbox.height - event.y FigureCanvasBase.motion_notify_event(self, x, y, guiEvent=event) + def button_press_event(self, event): x = event.x # flipy so y=0 is bottom of canvas Modified: trunk/matplotlib/lib/matplotlib/backends/backend_wx.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_wx.py 2008-06-23 21:39:11 UTC (rev 5652) +++ trunk/matplotlib/lib/matplotlib/backends/backend_wx.py 2008-06-24 04:17:21 UTC (rev 5653) @@ -713,6 +713,7 @@ self.Bind(wx.EVT_LEFT_UP, self._onLeftButtonUp) self.Bind(wx.EVT_MOTION, self._onMotion) self.Bind(wx.EVT_LEAVE_WINDOW, self._onLeave) + self.Bind(wx.EVT_IDLE, self._onIdle) else: # Event handlers 2.4 wx.EVT_SIZE(self, self._onSize) @@ -728,6 +729,7 @@ wx.EVT_LEFT_UP(self, self._onLeftButtonUp) wx.EVT_MOTION(self, self._onMotion) wx.EVT_LEAVE_WINDOW(self, self._onLeave) + wx.EVT_IDLE(self, self._onIdle) self.macros = {} # dict from wx id to seq of macros @@ -1078,6 +1080,11 @@ return key + def _onIdle(self, evt): + 'a GUI idle event' + evt.Skip() + FigureCanvasBase.idle_event(self, guiEvent=evt) + def _onKeyDown(self, evt): """Capture key press.""" key = self._get_key(evt) Modified: trunk/matplotlib/lib/matplotlib/cbook.py =================================================================== --- trunk/matplotlib/lib/matplotlib/cbook.py 2008-06-23 21:39:11 UTC (rev 5652) +++ trunk/matplotlib/lib/matplotlib/cbook.py 2008-06-24 04:17:21 UTC (rev 5653) @@ -3,7 +3,7 @@ from the Python Cookbook -- hence the name cbook """ from __future__ import generators -import re, os, errno, sys, StringIO, traceback, locale +import re, os, errno, sys, StringIO, traceback, locale, threading import time, datetime import numpy as np @@ -152,7 +152,65 @@ func(*args, **kwargs) +class Scheduler(threading.Thread): + """ + Base class for timeout and idle scheduling + """ + idlelock = threading.Lock() + id = 0 + def __init__(self): + threading.Thread.__init__(self) + self.id = Scheduler.id + self._stopped = False + Scheduler.id += 1 + self._stopevent = threading.Event() + + def stop(self): + if self._stopped: return + self._stopevent.set() + self.join() + self._stopped = True + +class Timeout(Scheduler): + """ + Schedule recurring events with a wait time in seconds + """ + def __init__(self, wait, func): + Scheduler.__init__(self) + self.wait = wait + self.func = func + + def run(self): + + while not self._stopevent.isSet(): + self._stopevent.wait(self.wait) + Scheduler.idlelock.acquire() + b = self.func(self) + Scheduler.idlelock.release() + if not b: break + +class Idle(Scheduler): + """ + Schedule callbacks when scheduler is idle + """ + # the prototype impl is a bit of a poor man's idle handler. It + # just implements a short wait time. But it will provide a + # placeholder for a proper impl ater + waittime = 0.05 + def __init__(self, func): + Scheduler.__init__(self) + self.func = func + + def run(self): + + while not self._stopevent.isSet(): + self._stopevent.wait(Idle.waittime) + Scheduler.idlelock.acquire() + b = self.func(self) + Scheduler.idlelock.release() + if not b: break + class silent_list(list): """ override repr when returning a list of matplotlib artists to This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |