使用BLIT实现实时绘图时无法清除旧线条的问题
解决Matplotlib实时绘图Blit模式下重复线条问题
问题根源分析
- 背景保存时机错误:每个
Plot实例初始化时就保存背景,但后续创建的子图会修改整个画布,导致保存的bg不是最终的干净画布状态。 - 重复绘制静态元素:每次
update都重新调用ax.legend()和ax.set_title(),这些静态元素未被包含在blit缓存中,会被重复绘制。 - 自动缩放破坏缓存:
ax.relim()和ax.autoscale_view()会触发坐标轴重绘,导致之前保存的背景失效,旧线条残留。
修改后的代码实现
修正后的Plot类
class Plot(): def __init__(self, fig, ax, grain, name, color) -> None: self.fig = fig self.ax = ax self.xData = range(grain) self.yData = [0] * grain self.name = name self.color = color # 初始化曲线,设置动画属性 self.ln, = self.ax.plot(self.xData, self.yData, animated=True, label=self.name, color=f"C{color}") # 初始化静态元素并标记为animated self.title = self.ax.set_title(self.name) self.legend = self.ax.legend() self.title.set_animated(True) self.legend.set_animated(True) # 暂不保存背景,统一在LiveGraph初始化完成后保存 self.bg = None def update(self, y): # 恢复背景 self.fig.canvas.restore_region(self.bg) # 更新数据 self.yData.append(y) self.yData.pop(0) self.ln.set_ydata(self.yData) # 如果需要自动缩放,需重新计算背景(可选) # self.ax.relim() # self.ax.autoscale_view() # self.bg = self.fig.canvas.copy_from_bbox(self.ax.bbox) # 重绘动态元素 self.ax.draw_artist(self.ln) self.ax.draw_artist(self.title) self.ax.draw_artist(self.legend) # 更新指定区域 self.fig.canvas.blit(self.ax.bbox) self.fig.canvas.flush_events()
修正后的LiveGraph类
import matplotlib.pyplot as plt import math class LiveGraph(): def __init__(self, plotNum, names) -> None: self.fig = plt.figure() self.plots = [] # 创建所有子图 for i in range(plotNum): ax = self.fig.add_subplot(plotNum, 1, i+1) plot = Plot(self.fig, ax, 100, names[i], i) self.plots.append(plot) # 所有元素初始化完成后,统一保存每个子图的背景 self.fig.canvas.draw() for plot in self.plots: plot.bg = self.fig.canvas.copy_from_bbox(plot.ax.bbox) self.tick = 0 plt.show(block=False) plt.pause(0.1) def update(self): self.tick += 1 y_val = math.sin(self.tick/10) for plot in self.plots: plot.update(y_val) if __name__ == "__main__": LG = LiveGraph(2, ["test1", "test2"]) while True: LG.update()
关键修改说明
- 延迟背景保存:在
LiveGraph中所有子图和静态元素创建完成后,先调用self.fig.canvas.draw()绘制整个画布,再保存每个子图的背景,确保bg是干净的初始状态。 - 静态元素标记动画:将标题、图例等静态元素设置为
animated=True,让blit机制将它们包含在缓存中,避免重复绘制。 - 移除重复静态元素绘制:不在
update中重复创建标题和图例,只在初始化时创建一次。 - 可选自动缩放处理:如果需要自动缩放,每次缩放后要重新保存背景,否则会导致线条残留(不需要自动缩放可直接注释相关代码)。
内容的提问来源于stack exchange,提问作者Paul Weder
相关产品推荐
相关产品推荐

