[英]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.