如何在Jupyter Notebook中运行plt.draw/plt.pause实现绘图实时更新?
我之前也碰到过这个问题,核心原因很明确:%matplotlib inline是静态渲染模式,它只会输出绘图的最终静态结果,完全不支持实时的画布更新操作。下面给你两个实用的解决办法,按需选择:
1. 切换到交互式Matplotlib后端(推荐)
直接把开头的魔法命令换成%matplotlib notebook或者%matplotlib widget(后者是Jupyter Lab官方推荐的,兼容性和交互体验更好),这两个后端都支持实时画布更新,你的原有代码只需要小调整就能正常运行:
%matplotlib widget import matplotlib.pyplot as plt import numpy as np class PosePlotter: def __init__(self): self.pose = np.array([0, 0, 0]) # 初始化位姿 # 显式创建画布和坐标轴,提前设置范围避免看不到图形 self.fig, self.ax = plt.subplots() self.ax.set_xlim(-2, 2) self.ax.set_ylim(-2, 2) self.point, = self.ax.plot([],[], 'o', color='green') self.line, = self.ax.plot([],[], ls="-", color='red', lw=2) plt.show(block=False) def plot_pose(self): # 更新点和线的数据 self.point.set_data(self.pose[0], self.pose[1]) end_x = self.pose[0] - 0.5 * np.cos(self.pose[2]) end_y = self.pose[1] + 0.5 * np.sin(self.pose[2]) self.line.set_data([self.pose[0], end_x], [self.pose[1], end_y]) self.fig.canvas.draw() # 显式触发画布更新,比单纯pause更可靠 plt.pause(0.0001) # 测试实时更新效果 plotter = PosePlotter() for i in range(100): # 模拟位姿变化 plotter.pose = np.array([np.cos(i/10), np.sin(i/10), i/10]) plotter.plot_pose()
这里额外做了两个关键优化:提前设置坐标轴范围(避免初始时看不到图形),显式调用canvas.draw()确保画布及时更新,有些场景下plt.pause()会自动触发刷新,但显式调用更稳定。
2. 在inline模式下模拟实时更新(迫不得已时用)
如果因为某些限制必须保留%matplotlib inline,可以用IPython的clear_output函数逐帧清除旧图、绘制新图,模拟出实时更新的效果:
%matplotlib inline import matplotlib.pyplot as plt import numpy as np from IPython.display import clear_output class PosePlotter: def __init__(self): self.pose = np.array([0, 0, 0]) def plot_pose(self): plt.clf() # 清除当前画布 ax = plt.gca() ax.set_xlim(-2, 2) ax.set_ylim(-2, 2) # 重新绘制点和线 ax.plot(self.pose[0], self.pose[1], 'o', color='green') end_x = self.pose[0] - 0.5 * np.cos(self.pose[2]) end_y = self.pose[1] + 0.5 * np.sin(self.pose[2]) ax.plot([self.pose[0], end_x], [self.pose[1], end_y], ls="-", color='red', lw=2) plt.show() clear_output(wait=True) # 等待新图生成后再清除旧输出,减少闪烁 # 测试效果 plotter = PosePlotter() for i in range(100): plotter.pose = np.array([np.cos(i/10), np.sin(i/10), i/10]) plotter.plot_pose()
这种方式的缺点是每次都要重新绘制整个画布,性能不如交互式后端,而且会有轻微闪烁,但在只能用inline模式的场景下是可行的。
内容的提问来源于stack exchange,提问作者MoneyBall
相关产品推荐
相关产品推荐

