From 52f5a87e92a3773d2bfb4e6d301f9ba66f2e5274 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Fri, 27 Mar 2015 22:48:34 -0400 Subject: [PATCH 1/2] ENH : add blit support to webagg and nbagg Closes #4288 --- .../backends/backend_webagg_core.py | 22 +++++++++- .../backends/web_backend/nbagg_uat.ipynb | 44 ++++++++++++++++++- 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/backends/backend_webagg_core.py b/lib/matplotlib/backends/backend_webagg_core.py index 008818386b53..daf24f2022ee 100644 --- a/lib/matplotlib/backends/backend_webagg_core.py +++ b/lib/matplotlib/backends/backend_webagg_core.py @@ -138,7 +138,7 @@ def _handle_key(key): class FigureCanvasWebAggCore(backend_agg.FigureCanvasAgg): - supports_blit = False + supports_blit = True def __init__(self, *args, **kwargs): backend_agg.FigureCanvasAgg.__init__(self, *args, **kwargs) @@ -180,9 +180,22 @@ def draw(self): # Swap the frames self.manager.refresh_all() + def blit(self, bbox=None): + """ + Blit the region in bbox + """ + self._png_is_old = True + self.manager.refresh_all() + def draw_idle(self): self.send_event("draw") + def copy_from_bbox(self, bbox): + # we really want the old one (which is what is currently 'on screen') + # this will behave badly if `draw` has never been called. + renderer = self._last_renderer + return renderer.copy_from_bbox(bbox) + def set_image_mode(self, mode): """ Set the image mode for any subsequent images which will be sent @@ -241,6 +254,13 @@ def get_diff_image(self): # Swap the renderer frames self._renderer, self._last_renderer = ( self._last_renderer, renderer) + + # update the cached renders of the Figure and Axes so that + # draw_artist() methods work as expected. + self.figure._cachedRenderer = self._renderer + for ax in self.figure.axes: + ax._cachedRenderer = self._renderer + self._force_full = False self._png_is_old = False return self._png_buffer.getvalue() diff --git a/lib/matplotlib/backends/web_backend/nbagg_uat.ipynb b/lib/matplotlib/backends/web_backend/nbagg_uat.ipynb index a8525ea28ed5..f928896a529d 100644 --- a/lib/matplotlib/backends/web_backend/nbagg_uat.ipynb +++ b/lib/matplotlib/backends/web_backend/nbagg_uat.ipynb @@ -1,7 +1,7 @@ { "metadata": { "name": "", - "signature": "sha256:a1ac68aba163c75eab3d1fc91aa4d9a8ca66b09159619563827a19967d96814b" + "signature": "sha256:b18e2b0bb3d6c7d68852e1691d2a961bb7c0dd6b254113a763473bbe83dd4f0e" }, "nbformat": 3, "nbformat_minor": 0, @@ -439,6 +439,48 @@ "language": "python", "metadata": {}, "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### UAT 17 - Blitting\n", + "\n", + "Clicking on the figure should plot a green horizontal line moving up the axes.\n", + "\n" + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "import matplotlib.pyplot as plt\n", + "\n", + "prev_artist = None\n", + "cur_y = 0.1\n", + "\n", + "def onclick_handle(event):\n", + " \"\"\"Should draw elevating green line on each mouse click\"\"\"\n", + " global ax, bg, prev_artist, cur_y\n", + " ax.figure.canvas.restore_region(bg)\n", + " if prev_artist:\n", + " prev_artist.remove()\n", + " cur_y += 0.1\n", + " prev_artist = ax.plot([0, 1], [cur_y, cur_y], 'g')[0]\n", + " ax.draw_artist(prev_artist)\n", + " ax.figure.canvas.blit(ax.bbox)\n", + " print(\"Drew line\")\n", + "\n", + "fig, ax = plt.subplots()\n", + "ax.plot([0, 1], [0, 1], 'r')\n", + "plt.show()\n", + "ax.figure.canvas.draw()\n", + "bg = ax.figure.canvas.copy_from_bbox(ax.bbox)\n", + "ax.figure.canvas.mpl_connect('button_press_event', onclick_handle)" + ], + "language": "python", + "metadata": {}, + "outputs": [] } ], "metadata": {} From de094871dbf84ab17855cfe91760f7da3cb224b7 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Sat, 4 Apr 2015 21:31:18 -0400 Subject: [PATCH 2/2] WIP : minor tweak to try and fix animation fixes some issues (makes sure we always have a renderer), but something much worse is wrong underneath (the animation objects goes crazy and eats all of the CPU). --- lib/matplotlib/backends/backend_webagg_core.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/backends/backend_webagg_core.py b/lib/matplotlib/backends/backend_webagg_core.py index daf24f2022ee..9031693f1e55 100644 --- a/lib/matplotlib/backends/backend_webagg_core.py +++ b/lib/matplotlib/backends/backend_webagg_core.py @@ -191,8 +191,8 @@ def draw_idle(self): self.send_event("draw") def copy_from_bbox(self, bbox): - # we really want the old one (which is what is currently 'on screen') - # this will behave badly if `draw` has never been called. + # make sure both renderers exist + self.get_renderer() renderer = self._last_renderer return renderer.copy_from_bbox(bbox)