Python 在Matplotlib中另一个文本对象的边界处绘制文本

Python 在Matplotlib中另一个文本对象的边界处绘制文本,python,text,matplotlib,Python,Text,Matplotlib,我试图在Matplotlib中的图形上创建文本标签,我想用不同的颜色突出显示某些单词。由于Matplotlib没有本机功能来执行此操作,我想我可以将两个文本元素相邻放置,但在正确对齐它们时遇到了问题 我找到了一个相关的特性请求,下面的示例输出是我想要模拟的,但是我无法复制它,即使我复制了他使用的代码并将其保存到PNG(这是我得到的)。Matplotlib是否改变了其API处理翻译或获取文本边界的方式 我怎样才能做到这一点?欢迎提供任何指导。您链接的代码只需稍加修改即可正常工作。这是一个很好的示例

我试图在Matplotlib中的图形上创建文本标签,我想用不同的颜色突出显示某些单词。由于Matplotlib没有本机功能来执行此操作,我想我可以将两个文本元素相邻放置,但在正确对齐它们时遇到了问题

我找到了一个相关的特性请求,下面的示例输出是我想要模拟的,但是我无法复制它,即使我复制了他使用的代码并将其保存到PNG(这是我得到的)。Matplotlib是否改变了其API处理翻译或获取文本边界的方式


我怎样才能做到这一点?欢迎提供任何指导。

您链接的代码只需稍加修改即可正常工作。这是一个很好的示例,说明了您想要做什么,因此我不会发布任何真正的新代码,只发布我的修改版本:

将matplotlib.pyplot作为plt导入 从matplotlib导入转换

def rainbow_text(x,y,ls,lc,**kw):
    """
    Take a list of strings ``ls`` and colors ``lc`` and place them next to each
    other, with text ls[i] being shown in color lc[i].

    This example shows how to do both vertical and horizontal text, and will
    pass all keyword arguments to plt.text, so you can set the font size,
    family, etc.
    """
    t = plt.gca().transData
    fig = plt.gcf()

    #### note: this line moved down ....### 
    #plt.show()                           #
    #######################################
    #horizontal version
    for s,c in zip(ls,lc):
        text = plt.text(x,y," "+s+" ",color=c, transform=t, **kw)
        text.draw(fig.canvas.get_renderer())
        ex = text.get_window_extent()
        t = transforms.offset_copy(text._transform, x=ex.width, units='dots')

    #vertical version
    for s,c in zip(ls,lc):
        text = plt.text(x,y," "+s+" ",color=c, transform=t,
                rotation=90,va='bottom',ha='center',**kw)
        text.draw(fig.canvas.get_renderer())
        ex = text.get_window_extent()
        t = transforms.offset_copy(text._transform, y=ex.height, units='dots')

    t = plt.gca().transData
    fig = plt.gcf()
    plt.show() ############### when this is here, you can see that 
               ############### all unicorns poo rainbows ;-)

plt.figure()

rainbow_text(0.0,0.0,"all unicorns poop rainbows ! ! !".split(), 
        ['red', 'orange', 'brown', 'green', 'blue', 'purple', 'black'],
        size=30)
### worked on matplotlib version 1.1.0 on Debian Wheezy. Which version did you try?

我只是为了我自己的目的而玩弄你的代码,我想我应该在这里添加我所做的

此示例是对代码的修改,允许任何文本角度旋转。但是,这仅适用于文本
va='bottom'
ha='left'

import math
import numpy

from numpy.linalg import inv
from matplotlib import transforms
from matplotlib import pyplot as plt

def rainbow_text(x, y, ls, lc, theta, **kwargs):
    fig = plt.gcf()
    axis = plt.gca()

    theta_rad = math.radians(theta)
    text_trans = axis.transData
    for s, c in zip(ls, lc):
        text = plt.text(x, y, " %s " %s,
                        verticalalignment='bottom',
                        horizontalalignment='left',
                        color=c,
                        transform=text_trans,
                        rotation=theta,
                        **kwargs)

        text.draw(axis.figure.canvas.get_renderer())

        # solve for the text width and height
        bbox = text.get_window_extent(axis.figure.canvas.get_renderer())
        theta_mat = numpy.array([[math.cos(theta_rad), math.sin(theta_rad)],
                                 [math.sin(theta_rad), math.cos(theta_rad)]])
        txt_size = numpy.dot(inv(theta_mat),
                             numpy.array([bbox.width, bbox.height]))

        # plot the bounds for each word (only works with axis autoscaling off)
        for i in range(4):
            bounds = bbox.corners()
            point = axis.transData.inverted().transform(bounds[i])
            plt.plot(point[0], point[1], '*', color=c)

        x_offset = txt_size[0] * math.cos(theta_rad)
        y_offset = txt_size[0] * math.sin(theta_rad)
        text_trans = transforms.offset_copy(text.get_transform(),
                                            fig=fig,
                                            x=x_offset,
                                            y=y_offset,
                                            units='points')


plt.figure()
plt.axis([0, 5, 0, 5])

rainbow_text(1, 1, "all unicorns poop rainbows ! ! !".split(),
             ['red', 'orange', 'brown', 'green', 'blue', 'purple', 'black'],
             20, size=20)
plt.savefig('blarg.png', ext='png')
plt.show()

我试图运行这段代码,但我得到了一个类似的结果,即单词相互重叠。你能试着做一下
plt.savefig('filename')
,看看PNG的输出是否正确吗?我试图在matplotlib源代码中使用此功能,我使用的是来自其GitHub的最新克隆的构建。我可以尝试安装打包的版本,看看是否有帮助。是否有其他无法正确设置的内容可能导致此问题?png后端似乎有问题。我的情况也是如此。我尝试将图像保存为PDF格式,效果更好。尝试播放一点宽度和高度(x=ex.width*0.9会改变垂直文本的起始位置。您还可以更改y=ex.height*1.1,使其更适合。请注意,制作pdf时,您可以使用(figprops=dict(figsize=(10,10))指定pdf的大小#这是10英寸乘10英寸…但它在使用大字体时效果非常好。fig=plt.figure(**figprops)。试试这个,让我知道你得到了什么。在我将后端更改为WXAgg/GTKAgg后,它似乎工作正常。唯一的问题是,当我尝试使用“this word is”和“red”等段时,它会将它们捆绑为“this word isred”在某些情况下,可能是由于第一个词组中的尾随空格。如果我将该空格转移到下一个词组,它会工作得很好。谢谢!嘿,再一次。我只是注意到PNG仍然不工作。看起来它没有使用渲染器获得正确的范围或没有正确翻译…我想这是第一件看起来像int的事情o、 嘿,我又来了!呜呜!我真的弄明白了;后端很好,实际上是
offset\u copy
的问题。我注意到
get\u window\u extent
函数应该以图形单位返回它,所以我想知道“点”是否应该改为“点”。但是,尝试这样做时,间距太大了,因此,我进入了
offset\u copy
函数定义,注意到它被硬编码为除以72,而不是从
fig.DPI
获取DPI。这样做之后,在交互式和PNG版本中分离效果非常好!我应该提交这个更改,也许!