繁体   English   中英

如何在matplotlib中制作自定义文本object交互

[英]How to make a customized Text object interactive in matplotlib

我有一个自定义的Text object,和下面这个简化的object逻辑是一样的:

import matplotlib.pyplot as plt
from matplotlib.text import Text

class MyText(Text):
    def __init__(self, x, y, txt, height, **kwargs):
        super().__init__(x, y, txt, **kwargs)
        self.height = height
        
    def mydraw(self, ax):
        txt = ax.add_artist(self)
        myset_fontsize(txt, self.height)
        return self
    
    def set_height(self, height):
        self.height = height
        #myset_fontsize(self, height)


def myset_fontsize(txtobj, height):
    trans = txtobj.get_transform()
    pixels, _ = trans.transform((txtobj.height, 0)) - trans.transform((0,0))
    dpi = txtobj.axes.get_figure().get_dpi()
    points = pixels / dpi * 72
    txtobj.set_fontsize(points)
           
if __name__ == '__main__':
    fig, ax = plt.subplots()
    ax.grid(True)
    txt = MyText(0.2, 0.2, 'hello', 0.1)
    txt.mydraw(ax)

MyText与内置Text的不同之处在于 fontsize 取决于height ,例如,指定数据坐标中文本的高度。 除此之外, MyText几乎与Text相同。 示例代码给出下图:

在此处输入图像描述

这适用于 static 图像。 但是,我希望MyTest具有交互性,其中包括以下目标:

  • 在交互式 plot 模式下, txt.set_height(0.5)动态更改字体大小。 我知道我可以添加一个片段作为评论显示,但如果MyText object 没有添加到轴, txt.set_height(0.5)将抛出一个AttributeError 简而言之, txt.set_height()的行为应该类似于txt.set_fontsize()

  • 当通过拖动 plot window 调整图形大小时, MyText应相应更改字体大小,即数据坐标中文本的高度应保持不变。 但目前调整图形大小时字体大小不变。 我找到了这个答案,但是mpl_connect需要一些方法来获取Figure object,我希望MyText在调用txt.mydraw(ax)后进行交互。

在此处输入图像描述

  • 当我改变图形的纵横比时, MyText应该相应地改变字体大小,与第二点相同。

感谢您的任何想法!

如果只需要将字体从window改成大小。 安装了通过调整 window 的大小触发的事件处理程序。Fonts 大小绑定到 window 大小的一侧(在本例中为宽度)。

import matplotlib.pyplot as plt
from matplotlib.text import Text


class MyText(Text):
    def __init__(self, x, y, txt, height, **kwargs):
        super().__init__(x, y, txt, **kwargs)
        self.height = height
        self.event_text = fig.canvas.mpl_connect('resize_event', self.mysize)

    def mysize(event, ax):
        fig = plt.gcf()
        size_ = fig.get_size_inches()
        txt.set_fontsize(size_[0]*5)

    def mydraw(self, ax):
        txt = ax.add_artist(self)
        myset_fontsize(txt, self.height)
        return self

    def set_height(self, height):
        self.height = height
        # myset_fontsize(self, height)


def myset_fontsize(txtobj, height):
    trans = txtobj.get_transform()
    pixels, _ = trans.transform((txtobj.height, 0)) - trans.transform((0, 0))
    dpi = txtobj.axes.get_figure().get_dpi()
    points = pixels / dpi * 72
    txtobj.set_fontsize(points)


if __name__ == '__main__':
    fig, ax = plt.subplots()
    ax.grid(True)
    txt = MyText(0.2, 0.2, 'hello', 0.1)
    txt.mydraw(ax)
    plt.show()

看完用户指南后,我发现每个艺术家都有一个stale的属性,这是重新渲染图形的某种信号。 完整的解决方案如下:

import matplotlib.pyplot as plt
from matplotlib.text import Text

class MyText(Text):
    def __init__(self, x, y, txt, height, **kwargs):
        super().__init__(x, y, txt, **kwargs)
        self.height = height

    def __call__(self, event):
        # When calling myset_fontsize, `self.stale` will be `True` due to `self.set_fontsize()` in the function body.
        myset_fontsize(self, self.height)
        
    def mydraw(self, ax):
        txt = ax.add_artist(self)

        # Connect "draw_event" so that once a draw event happens, a new fontsize is calculated and mark the `Text` object is stale.
        ax.get_figure().canvas.mpl_connect('draw_event', self)

        return txt
    
    def set_height(self, height):
        self.height = height
        # When a new height is set, then the
        #`Text` object is stale, which will 
        # forward the signal of re-rendering 
        # the figure to its parent.
        self.stale = True


def myset_fontsize(txtobj, height):
    trans = txtobj.get_transform()
    pixels, _ = trans.transform((txtobj.height, 0)) - trans.transform((0,0))
    dpi = txtobj.axes.get_figure().get_dpi()
    points = pixels / dpi * 72
    txtobj.set_fontsize(points)

这个解决方案几乎解决了我的问题,尽管它并不完美。 这有点低效。

任何改进表示赞赏。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM