如何在已经绘制标题时更新标题在 matplotlib 中的位置

How to update a title's position in matplotlib when it has been drawn already

我正在尝试将 matplotlib Text 实例自动移动到某些 plt.tight_layoutconstrained_layout 未考虑的注释上方。

但是,我似乎无法使用 Text.set_position 更新标题位置并在之后重新绘制(无论是在使用 fig.canvas.draw() 每次更新时还是在调用 title_text_instance.draw(renderer=fig.canvas.get_renderer()) 时)。

文本本身似乎更新得很好,另一个注释也是如此,这很奇怪,因为标题和注释都是 Text objects.

为什么下面代码中的标题位置没有更新?

动画说明;标题文本和注释位置按预期更新,但其位置保持不变:

代码:

#!/usr/bin/env/python3
import matplotlib.pyplot as plt
import matplotlib as mpl

N_FRAMES: int = 10
# Setting up the example.
mpl.use("TkAgg")
fig, ax = plt.subplots(figsize=(2, 1), dpi=300)
ax.plot(range(10), range(10))
t = ax.set_title("Example title", fontsize=6, alpha=.8, clip_on=False)

atext1 = '\n'.join(['Overlapping extra-axis annotation',
                    'above which I want to move the title',
                    'undetected by tight_layout or constrained_layout'])
atext2 = 'this annotation moves just fine...'
a1 = ax.annotate(atext1, xycoords='axes fraction', xy=(.25, 1),
                 rotation=10, clip_on=False, fontsize=3, color='r', alpha=.6)
a2 = ax.annotate(atext2, xycoords='axes fraction', xy=(.5, .5),
                 clip_on=False, fontsize=4, color='g')
fig.canvas.draw()
plt.tight_layout()
# ^^ Leaving out plt.tight_layout doesn't
# make a difference w.r.t position updates

for yoffset in range(N_FRAMES):
    new_position = (t.get_position()[0], t.get_position()[1] - .5 + (yoffset / 2))
    newpostext = '(' + ', '.join(f'{pos:.2f}' for pos in new_position) + ')'

    # Changing positions
    print(f'Set new position to', newpostext)
    t.set_position(new_position)  # Doesn't work
    a2.set_position(new_position)  # Works fine

    t.set_text(f"Supposedly repositioned title position: \n (x, y) = {newpostext}")
    plt.pause(.5)

plt.get_current_fig_manager().window.resizable(False, False)
plt.show(block=False)
plt.close(fig)

标题有一个内部 属性 _autotitlepos set to True unless you explicitly specify the y position of the title。因此,为了能够手动设置标题位置,您需要在设置标题时为 y 提供一个值,例如1的默认值:

t = ax.set_title("Example title", fontsize=6, alpha=.8, clip_on=False, y=1)

(最低 matplotlib 版本 3.3.0,参见 PR #17127