簡體   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