动画化Matplotlib面板 - blit留下旧帧

3 投票
3 回答
2520 浏览
提问于 2025-04-16 19:13

我有一个使用wxPython制作的应用程序,其中包含一个matplotlib面板(这个面板是通过wxmpl实现的,不过我也见过用普通的FigureCanvasWxAgg画布实现的)。

我想在这个面板中给其中一个图表添加动画,之前我也做过类似的事情。现在我采用的方法是推荐的步骤:

  • 先复制背景
  • 然后绘制图表
  • [...]
  • 再恢复背景
  • 更新线条数据
  • 绘制艺术效果
  • 最后进行快速绘制

问题是,图表在恢复背景后并没有被“覆盖”,而是依然留在那里,导致整个画面看起来很乱。

一些(简化的)代码:

fig = self.myPanel.get_figure()
ax_top = fig.add_subplot(211)
ax_bottom = self.fig.add_subplot(212)
canvas = fig.canvas
canvas.draw()
bg_top = canvas.copy_from_bbox(ax_top.bbox)
bg_bottom = canvas.copy_from_bbox(ax_bottom.bbox)
line, = ax_bottom.plot(x, y, 'k', animated=True)

然后,在更新时:

canvas.restore_region(bg_bottom)
line.set_ydata(new_y)
ax_bottom.draw_artist(line)
canvas.blit(ax_bottom.bbox)

新的线条被绘制出来(而且速度很快!:),但不知为何,它是在旧线条的上面绘制的。有人能猜出这是为什么吗?

3 个回答

0

你必须把一个叫‘draw_event’的东西链接到新的背景图上。否则,旧的背景图会一直覆盖在你想要的背景上,这样你只能通过工具栏里的缩放或平移来查看。对我来说,这样做是有效的。

马丁。

2

我用FigureCanvasWxAgg测试过。我觉得发生的情况是,在你初始化面板和坐标轴之后,再绘制的时候,坐标轴可能被移动或调整了大小。你可以试着等到真正绘制的时候再获取那些背景,也就是说,在你初始化框架/面板的时候:

...
bg_top = None
bg_bottom = None
line, = ax_bottom.plot(x, y, 'k', animated=True)
...

然后在你更新的时候:

def update(self, evt):
    if bf_top is None:
        bg_top = canvas.copy_from_bbox(ax_top.bbox)
        bg_bottom = canvas.copy_from_bbox(ax_bottom.bbox)
    canvas.restore_region(bg_bottom)
    line.set_ydata(new_y)
    ax_bottom.draw_artist(line)
    canvas.blit(ax_bottom.bbox)
4

应要求添加的回答 :)

在调用 fig.canvas.copy_from_bbox 之前,先试着调用 fig.canvas.draw()。具体的效果会根据不同的后台而有所不同,所以在不同的平台上表现也会不一样。不过一般来说,你需要先把画布画出来,然后才能从中复制东西。

撰写回答