基于 John Hunter的answer to a question regarding using patches in animations here,我的印象是:
True
创建patch
个对象。axis
方法将其添加到现有axis
(假设ax
对象称为add_patch
)。patch
时,我会:ax.draw_artist(patch)
。这样做,我遇到以下错误:
File "environment.py", line 254, in animation_function
ax.draw_artist(patches[index])
File "A:\Anaconda\lib\site-packages\matplotlib\axes\_base.py", line 2121, in draw_artist
assert self._cachedRenderer is not None
AssertionError
顶级代码的组织如下:
一个函数从数据创建补丁,然后将它们添加到axis
对象 - 基本上,我得到一个补丁对象列表,patches
,其中每个补丁都已添加到ax
; 我认为这个问题可能就在这里,因为patches
中的补丁对象
动画功能使用从ax
收到的号码(让我们说n
)来引用相关的补丁对象,然后调用FuncAnimation
起初我正在做以下事情:
ax.draw_artist(patches[n])
然后,在reading the documentation之后,表示返回了一个补丁对象(可能现在连接到一个轴对象?),我尝试了以下内容:
patches = []
...
patch = mpatches.PathPatch(...)
patch.set_animated(True)
ax.add_patch(patch)
patches.append(patch)
...
ax.draw_artist(patches[n])
然而,问题仍然存在。
您能评论一下您认为该问题可能是什么,或者我可能需要提供其他信息才能找出问题?
编辑:出现错误的顶级函数。
patches = []
...
patch = mpatches.PathPatch(...)
patch.set_animated(True)
ax_patch = ax.add_patch(patch)
patches.append(ax_patch)
...
ax.draw_artist(patches[n])
答案 0 :(得分:2)
您正确理解了所有内容,但遗漏了几个较低级别的步骤。 renderer
尚未初始化,并且您收到反映该错误的错误。
简而言之,在第一次绘制情节之前,您无法使用draw_artist
。在使用fig.canvas.draw()
之前,您需要至少召唤一次fig.canvas.get_renderer()
(在某些情况下,您只能使用draw_artist
)。Artist
。
如果你遇到这个问题,通常是因为你正试图去对抗谷物"做一些最好不要直接处理的事情。
你到底想要做什么?可能有一种更简单的方法来解决这个问题(例如,如果您尝试获取背景,请将此部分代码放入回调事件的回调中)。
让我备份并解释发生了什么。 Matplotlib FigureCanvas
使用fig.canvas
的实例(例如Renderer
)在fig.canvas.renderer
(例如renderer
)上绘制。 ax.draw_artist
是后端特定的和低级别的。你通常不会直接触摸它。
fig.canvas.draw
是比artist.draw(renderer)
更低级别的功能。更具体地说,它是renderer
的简写。
初始化canvas
相对较慢,因此除非图形的大小或dpi发生变化,否则它会被缓存并重复使用。这就是你所得到的错误:fig.canvas.get_renderer()
还没有渲染器。
您有几种不同的选择。您可以手动初始化渲染器(简单的方法是调用fig.canvas.draw()
)。但是,有时候您需要获取某些内容(例如文本对象的大小),直到它被绘制之后才能定义。在这种情况下,你需要一个完整的" matplotlib.animation
。
但是,通常情况下,遇到这样的事情表明这是一种更简单的方法。通常,最好将需要绘制的代码放入到draw事件的回调中。 (特别是如果它取决于图形的确切大小 - 例如blitting的背景)。
如果您正在使用import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation
def main():
fig, ax = plt.subplots()
p = Plotter(ax)
# Note: We need to save a referce to the animation object, otherwise it
# will be garbage collected and never properly animate.
anim = matplotlib.animation.FuncAnimation(fig, p.update,
init_func=p.anim_init)
plt.show()
class Plotter(object):
def __init__(self, ax):
self.ax = ax
def anim_init(self):
self.triangles = [self.random_triangle() for _ in range(10)]
# Initially, show a blank plot...
for tri in self.triangles:
tri.set_visible(False)
return self.triangles
def update(self, i):
"""Animation step."""
# Hide all triangles
for tri in self.triangles:
tri.set(visible=False)
# pick 2 at random to show (e.g. your patch_indices_per_timestep)
for tri in np.random.choice(self.triangles, size=2):
tri.set(visible=True)
return self.triangles
def random_triangle(self):
x, y = np.random.random((2,3))
x += 10 * np.random.random(1)
y += 10 * np.random.random(1)
return self.ax.fill(x, y)[0]
main()
框架,那么您不需要在更新功能中绘制艺术家。动画框架将为您完成这一步骤。
听起来你只是试图只展示你在每个时间步都画出的艺术家的一部分?
如果是这样,您可以考虑切换其可见性。作为一个简单的例子:
union all