Matplotlib图例高度(以像素为单位)

5

我需要知道图例的像素大小。从任何函数中,我似乎只能获得高度=1。我已经尝试过以下方法:

这将返回1。

height = legend.get_frame().get_bbox_to_anchor().height

这将返回 [0,0],[1.,1.]。
box = legend.get_window_extent().get_points()

这也会返回 [0,0],[1.,1.]。
box = legend.get_frame().get_bbox().get_points()

所有这些都会返回1,即使图例的大小发生了变化!发生了什么?

你是如何创建图例的?type(leg.get_frame())返回什么?你使用的matplotlib版本是什么? - Paul
1个回答

5
这是因为你还没有绘制画布。
在 matplotlib 中,像素值根本不存在(或者说,存在但与屏幕或其他输出无关),直到画布被绘制出来。
有很多原因,但我暂时不想深入讲解。可以简单地说,matplotlib 试图尽可能保持通用性,并且通常避免在未绘制元素之前使用像素值。
作为一个简单的例子:
import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(range(10), label='Test')
legend = ax.legend(loc='upper left')

print 'Height of legend before canvas is drawn:'
print legend.get_window_extent().height

fig.canvas.draw()

print 'Height of legend after canvas is drawn:'
print legend.get_window_extent().height

然而,这只代表图例在屏幕上绘制时的像素高度!如果保存图形,它将以不同于屏幕上绘制的dpi(默认为100)保存,因此像素大小将不同。
有两种方法解决这个问题:
1. 快速且简单:在输出像素值之前绘制图形画布,并确保在保存时明确指定图形的dpi(例如fig.savefig('temp.png', dpi=fig.dpi))。
2. 推荐,但稍微复杂一些:连接一个回调到绘制事件,并且仅在图形绘制时使用像素值。这样可以在只绘制一次图形的情况下使用像素值。
以下是后一种方法的快速示例:
import matplotlib.pyplot as plt

def on_draw(event):
    fig = event.canvas.figure
    ax = fig.axes[0] # I'm assuming only one subplot here!!
    legend = ax.legend_ 
    print legend.get_window_extent().height

fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(range(10), label='Test')
legend = ax.legend(loc='upper left')

fig.canvas.mpl_connect('draw_event', on_draw)

fig.savefig('temp.png')

注意第一个和第二个示例中图例高度打印的不同之处。(在我的系统上,第二个示例为31.0,而第一个示例为24.8,但这将取决于您的.matplotlibrc文件中的默认值)。这种差异是由于默认fig.dpi(默认为80 dpi)和保存图形时的默认分辨率(默认为100 dpi)之间的不同造成的。希望这样讲述有些道理。

你知道为什么1*dpi在渲染后不会得出像素高度吗?也就是说,为什么在绘制之前它总是等于1? - Duncan
@Duncan - 基本上,matplotlib故意避免任何像素值的概念,直到您到达给定画布的渲染器为止。(对于matplotlib支持的许多后端,像素没有意义。如果您使用矢量后端,则真正的“像素”值不存在。)渲染器直到绘制图形的画布才存在。基本上,当没有渲染器时,您会看到默认值(0-1)。 (还有更多内容,但这就是要点。) - Joe Kington

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接