DEBUG.WIKI
晚安云;香港 CN2 ¥15/月
IPPeak:从目标地区访问网页,住宅代理、SEO 监测、广告验证
搬瓦工;先看线路,再选 VPS;CN2 GIA · 对应线路套餐;查看线路 →

Matplotlib 把 AnchoredText 加到 Figure,保存时却报 NoneType 没有 bbox

AnchoredText 仅加到 Figure 且未提供锚定矩形,绘制时可能读取空 axes.bbox。按标注归属添加到 Axes,或明确 Figure 坐标矩形。

fig.add_artist(AnchoredText(...)) 没有立刻报错,直到窗口重绘或 savefig() 才出现 AttributeError: 'NoneType' object has no attribute 'bbox'。先检查这个文本框要相对整张 Figure,还是相对其中某个 Axes 定位。

import matplotlib.pyplot as plt
from matplotlib.offsetbox import AnchoredText

fig, ax = plt.subplots()
fig.add_artist(AnchoredText("Example", loc="upper right"))
fig.savefig("figure.png")

loc 指定了角落,却没有提供用于锚定的矩形。正式 Matplotlib 3.11.2 中,未设置 bbox_to_anchor 时仍会读取 self.axes.bbox;仅把 Artist 加到 Figure,不会替它关联一个 Axes。这个失败也可能延迟到布局计算或导出阶段。

标注属于某个坐标轴时,让 Axes 持有它

图内某个子图的说明框,可通过对应坐标轴添加:

fig, ax = plt.subplots()
label = AnchoredText("Example", loc="upper right")
ax.add_artist(label)
fig.savefig("axes-label.png")

Axes.add_artist() 会设置 Artist 的 axes 归属,默认锚定矩形便有了对象。多子图时要选择正确的 ax;不要为了消除异常随便用第一个坐标轴,否则窗口缩放和布局调整后,文本框可能跟着错误的子图移动。

确实要相对整张图时,给出矩形与坐标变换

全图级标注不应依赖某个 Axes 的默认边框,可以显式指定归一化 Figure 范围:

fig, ax = plt.subplots()
label = AnchoredText(
    "Example",
    loc="upper right",
    bbox_to_anchor=(0, 0, 1, 1),
    bbox_transform=fig.transFigure,
)
fig.add_artist(label)
fig.savefig("figure-label.png")

四元组表示锚定矩形的左下角、宽和高,fig.transFigure 将它解释为整张 Figure 的归一化坐标。只填 (0, 0, 1, 1) 却漏掉变换,会落入不同的坐标解释,位置未必正确。不要把这里的 Figure 坐标直接换成数据坐标值。

这两种处理分别表达子图标注和全图标注。没有哪一种适合所有布局,也不需要修改 Matplotlib 安装目录里的 get_bbox_to_anchor()。

验收应触发真实绘制和输出,不能止于创建 Artist。检查保存文件中的文本、边框及位置,再调整窗口大小或导出尺寸,确认它随预定对象移动;使用 tight 或 constrained 布局的项目,还要检查是否裁切、是否挤占其他元素。示例输出采用独立文件名,实际工作应保留已有图和输入数据。

如果已经提供有效的锚定矩形,仍在其他对象上报 bbox,应沿完整调用栈定位那个对象。这里确认的是 AnchoredText 缺省锚定与 axes 归属,不能把所有 NoneType.bbox 都归给同一个添加方法,也不能把开发分支中的讨论当作某个正式版本已经改变默认行为。