使用 Qt4 后端的 matplotlib 存在缓存渲染器问题

matplotlib using Qt4 backend has issue with cached renderer

我试图使用 matplotlib 以更快的方式重新绘制图像,所以我没有重新绘制所有内容,而是使用 AxesImage class 的 set_data 方法,如下所示:

import numpy as np
import time
import matplotlib.pyplot as plt

fig, ax = plt.subplots()
img = plt.imshow(np.random.rand(100, 100))

img.set_data(np.random.rand(100, 100))
ax.draw_artist(ax.patch)
ax.draw_artist(img)
fig.canvas.update()
fig.canvas.flush_events()

我遇到了这个错误:

Traceback (most recent call last): ... ax.draw_artist(ax.patch) File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/matplotlib/axes/_base.py", line 2319, in draw_artist raise AttributeError(msg) AttributeError: draw_artist can only be used after an initial draw which caches the render

但是,如果我在 python shell (IPython) 中逐行 运行 脚本,它会工作并且没有任何错误。那么这个缓存渲染器背后的奥秘是什么?

编辑:添加一行 fig.canvas.draw() 解决了问题,现在剩下的问题是为什么 运行 在 IPython shell 中逐行设置它不会导致同样的错误?

如您所知,在调用 draw_artist:

之前,必须至少绘制一次 canvas 才能缓存渲染器

draw_artist(a)

This method can only be used after an initial draw which caches the renderer. It is used to efficiently update Axes data (axis ticks, labels, etc are not updated)


我猜测在你的 IPython 会话中你是 interactive mode 中的 运行 matplotlib,在这种情况下你对 plt.subplots 的初始调用将立即导致 canvas 要绘制的新图形和要缓存的渲染器。

要复制您在脚本中看到的 AttributeError,您可以使用 plt.ioff():

关闭交互模式
In [1]: plt.ioff()

In [2]: fig, ax = plt.subplots(1, 1)

In [3]: img = plt.imshow(np.random.rand(100, 100))

In [4]: img.set_data(np.random.rand(100, 100))

In [5]: ax.draw_artist(ax.patch)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-5-b54815e41caa> in <module>()
----> 1 ax.draw_artist(ax.patch)

/home/alistair/.venvs/core/local/lib/python2.7/site-packages/matplotlib/axes/_base.pyc in draw_artist(self, a)
   2317             msg = ('draw_artist can only be used after an initial draw which'
   2318                    ' caches the render')
-> 2319             raise AttributeError(msg)
   2320         a.draw(self._cachedRenderer)
   2321 

AttributeError: draw_artist can only be used after an initial draw which caches the render