You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Matplotlib动画中添加文本(支持外部显示)

Matplotlib动画添加文本的问题解决

问题根源

  • ax.cla()的副作用:每次帧更新时调用ax.cla()会清空轴上所有元素,包括初始化时创建的文本对象,导致后续无法修改显示内容。
  • 返回值格式错误:尝试返回(self.lines, self.text)时,self.lines是线条组成的元组,整体返回的是嵌套元组,而Matplotlib的blitting机制需要扁平的Artist对象列表/元组,因此触发AttributeError。

解决方案

关键修改点

  1. 将文本创建在Figure层级:用fig.text()替代ax.text(),避免被ax.cla()清除,同时方便放在绘图区域外部。
  2. 调整返回值为扁平结构:把所有需要更新的Artist(线条+文本)合并成一个扁平元组返回。
  3. 修正辅助函数逻辑:修复get_n函数的循环取数错误。

修改后的完整代码

import math
import sys

import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation, FFMpegWriter


line_x = [0,1,2,3,4,5,6,7,8,9,10,11,12]
line1_y = [3,5,7,9,11,19,23,26,29,31,37,40,45]
line2_y = [0,2,5,7,10,10,8,5,3,2,1,3,5]
line3_y = [39,38,32,29,26,22,19,13,10,8,7,6,3]

set_lines = [line1_y, line2_y, line3_y]
n_lineas = [1,2,3,1,3,2,3,1,3,2,1,2]

show = True
thecolors = ['blue','red','violet']
thelegends = ['unus','duo','tres']

if len(sys.argv)==2 and sys.argv[1]=='movie':
    show = False


def get_n(thelist,c):
    while c >= len(thelist):
        c -= len(thelist)  # 修正原代码的赋值错误
    return thelist[c]


class Update:
    def __init__(self, ax, limit_x, fig):
        self.ax = ax
        self.fig = fig
        self.lx = limit_x
        if limit_x != 0:
            self.ax.set_xlim(0, limit_x)
        self.ax.set_ylim(0, 45)
        self.ax.set_aspect('equal')
        self.ax.grid(True)
        self.ax.set_xlabel("Y (meters)")
        self.ax.set_ylabel("X (meters)")
        self.lines = ()
        self.counter = 0
        # 在Figure层级创建文本,放在绘图区域上方外部(归一化坐标)
        self.text = self.fig.text(0.5, 1.02, '', ha='center', fontsize=12)

    def __call__(self, frame):
        print("Frame: ", frame)
        lines = []

        # 清空轴内容,不影响Figure层级的文本
        self.ax.cla()
        self.ax.set_xlim(0, self.lx)
        self.ax.set_ylim(0, 45)
        self.ax.grid(True)
        self.ax.set_xlabel("Y (meters)")
        self.ax.set_ylabel("X (meters)")

        n_lines_this_time = get_n(n_lineas, self.counter)
        self.counter += 1
        print(n_lines_this_time,"lines this time")

        for myline in range(n_lines_this_time):
            line, = self.ax.plot([],[],'.-', color=thecolors[myline], label=thelegends[myline])
            line.set_xdata(line_x)
            line.set_ydata(set_lines[myline])
            lines.append(line)

        self.ax.legend()
        self.lines = tuple(lines)
        # 更新文本内容
        self.text.set_text(f"Frame {frame}")
        # 返回扁平的Artist对象元组:所有线条 + 文本
        return (*self.lines, self.text)

    def init(self):
        print("Init")
        line, = self.ax.plot([],[])
        self.text.set_text('')
        return line, self.text


fig, ax = plt.subplots(1, 1, figsize=(10,10))
plt.gcf().canvas.mpl_connect(
        'key_release_event',
        lambda event: sys.exit(0) if event.key == 'escape' else None)

ug_i = Update(ax, 13, fig)
anim = FuncAnimation(fig, ug_i, init_func=ug_i.init, frames=10, interval=1000, blit=True, repeat=False)

if not show:  
    writervideo = FFMpegWriter(fps=1)
    anim.save('whatever.mp4', writer=writervideo)
    print('done')
    plt.close()
else:
    plt.show()

额外说明

  • 文本使用Figure归一化坐标(0.5, 1.02),实现水平居中、轴上方外部的显示效果,ha='center'确保文本对齐。
  • 用ax.legend()替代全局的plt.legend(),避免状态干扰。

内容的提问来源于stack exchange,提问作者KansaiRobot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 06:25:21