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