在Matplotlib中给文字加边框

76

如何在matplotlib中对文本进行方框包围?我有三行不同颜色的文本:

 ax.text(2,1, 'alpha', color='red')
 ax.text(2,2, 'beta', color='cyan')
 ax.text(2,3, 'epsilon', color='black')

我看了这个教程http://matplotlib.org/users/recipes.html(最后一个例子),但是我无法解决问题。


1
你对食谱的最后一个示例有什么问题? - David Zwicker
@David 在这个例子中只有一行文本。我想知道如何在我写的文本周围拥有相同的框。按照这个示例,我可以像示例中一样在一行中编写文本(textstr ='$ \ mu =%.2f $ \ n $ \ mathrm {median} =%.2f $ \ n $ \ sigma =%.2f $'),但是如何改变文本的颜色呢? - Marika Blum
3个回答

157

正如你提供的示例所述,你可以使用 bbox关键字参数添加一个框。

我猜你可能对如何设置框的颜色等属性感到困惑?这里有一个快速的示例:

import matplotlib.pyplot as plt
fig, ax = plt.subplots()

ax.text(0.5, 0.8, 'Test', color='red', 
        bbox=dict(facecolor='none', edgecolor='red'))

ax.text(0.5, 0.6, 'Test', color='blue', 
        bbox=dict(facecolor='none', edgecolor='blue', pad=10.0))

ax.text(0.5, 0.4, 'Test', color='green', 
        bbox=dict(facecolor='none', edgecolor='green', boxstyle='round'))

ax.text(0.5, 0.2, 'Test', color='black', 
        bbox=dict(facecolor='none', edgecolor='black', boxstyle='round,pad=1'))

plt.show()

在此输入图像描述

最后两个是“花哨”的bbox补丁,因此填充等内容以不同的方式设置。(虽然对于像填充这样简单的东西来说有点烦人,但它使得幕后的实现更加简单。)

此外,如果您正在为图形添加标签,您可能会发现annotate是一个更好的选择。 它可以让您将文本放置在距离特定数据位置的偏移量(以点为单位)处,除其他外。


谢谢您的回复,但我可能没有很好地解释我的问题。我需要的是将这三行文本放在一个框中。 - Marika Blum
啊!并且使用不同的颜色,我猜呢?这是matplotlib长期存在的限制。(已经讨论过彻底更改文本渲染后端以允许此功能。)你基本上有两个选择。1)使用LaTeX(你需要“完整”的LaTeX,而不仅仅是matplotlib的数学文本),或者2)将它们分别绘制并在结果周围画一个框。这两个选项都在这里展示:https://dev59.com/_2ox5IYBdhLWcg3wf0Xl - Joe Kington

23

enter image description here 有一些在线文档(我能快速找到的最好的是http://matplotlib.org/users/annotations_guide.html),介绍了如何使用VPackerAnnotationBbox来组合几个具有不同字体属性的文本。

from matplotlib.offsetbox import TextArea, VPacker, AnnotationBbox
from pylab import *
fig = figure(1)
ax = gca()
texts = ['alpha','beta','epsilon']
colors = ['red','cyan','black']
Texts = []
for t,c in zip(texts,colors):
    Texts.append(TextArea(t,textprops=dict(color=c)))
texts_vbox = VPacker(children=Texts,pad=0,sep=0)
ann = AnnotationBbox(texts_vbox,(.02,.5),xycoords=ax.transAxes,
                            box_alignment=(0,.5),bboxprops = 
                            dict(facecolor='wheat',boxstyle='round',color='black'))
ann.set_figure(fig)
fig.artists.append(ann)

我不确定为什么需要最后两行代码,我认为倒数第二行已经足够了。


13
一个解决方案是探索文本对象的边界框并自己生成一个框。这不是很方便。也许我的示例可以改进,变换总是让我有点困惑。
import matplotlib.patches as patches
import matplotlib.pyplot as plt

fig, axs = plt.subplots(1,1)

t1 = axs.text(0.4,0.6, 'Hello world line 1', ha='center', color='red', weight='bold', transform=axs.transAxes)
t2 = axs.text(0.5,0.5, 'Hello world line 2', ha='center', color='green', weight='bold', transform=axs.transAxes)
t3 = axs.text(0.6,0.4, 'Hello world line 3', ha='center', color='blue', weight='bold', transform=axs.transAxes)

fig.canvas.draw()

textobjs = [t1,t2,t3]

xmin = min([t.get_window_extent().xmin for t in textobjs])
xmax = max([t.get_window_extent().xmax for t in textobjs])
ymin = min([t.get_window_extent().ymin for t in textobjs])
ymax = max([t.get_window_extent().ymax for t in textobjs])

xmin, ymin = fig.transFigure.inverted().transform((xmin, ymin))
xmax, ymax = fig.transFigure.inverted().transform((xmax, ymax))

rect = patches.Rectangle((xmin,ymin),xmax-xmin,ymax-ymin, facecolor='grey', alpha=0.2, transform=fig.transFigure)

axs.add_patch(rect)

你可能需要添加一个小缓冲区等,但是这个想法将保持不变。 输入图像描述

如果您想要一个准确位置的方框,例如当您使用matplotlib的ginput进行交互式绘图时需要点击方框,则此解决方案是最佳选择。 - ClimateUnboxed

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