Matplotlib中是否有一个函数或方法可以告诉您 哪些事件已连接,或者该侦听器正在调用什么代码?我四处张望,没有喜悦。我正在寻找一种通用的解决方案,而不是特定于后端的解决方案,但是我会尽力而为。
答案 0 :(得分:0)
在这种情况下,请不要担心matplotlib代码库-大部分情况下它是相当合理的pythonic且清晰易读(可能到处都是一两个骨架)。
我将通过步骤我将要通过的与您进行交流,以了解发生了什么以及可以访问哪些内容。
首先,从GitHub上带标签的matplotlib版本开始-它会使所有链接保持一致(并且不会随代码移动而腐烂)。 https://github.com/matplotlib/matplotlib/tree/v3.0.2
我们的切入点是我们通过mpl_connect
方法附加事件。在matplotlib代码库中对此内容进行快速搜索(使用"def mpl_connect"
,包括引号)会弹出https://github.com/matplotlib/matplotlib/blob/v3.0.2/lib/matplotlib/backend_bases.py#L2134-L2180。
self.callbacks.connect(s, func)
因此,现在我们需要弄清楚self.callbacks
在此对象上实际上是什么。我做了ctrl+f
来在此文件中找到文本self.callbacks =
。
https://github.com/matplotlib/matplotlib/blob/v3.0.2/lib/matplotlib/backend_bases.py#L1621
# a dictionary from event name to a dictionary that maps cid->func
self.callbacks = cbook.CallbackRegistry()
我们现在正在取得进步,并且每次都越来越深:)
逻辑上遵循导入,现在我们需要找出matplotlib.cbook.CallbackRegistry
的外观。 https://github.com/matplotlib/matplotlib/blob/v3.0.2/lib/matplotlib/cbook/init.py#L88。
具体来说,我们正在调用CallbackRegistry.connect
方法:https://github.com/matplotlib/matplotlib/blob/v3.0.2/lib/matplotlib/cbook/init.py#L162-L177。撰写本文时的实现:
def connect(self, s, func):
"""Register *func* to be called when signal *s* is generated.
"""
self._func_cid_map.setdefault(s, {})
try:
proxy = WeakMethod(func, self._remove_proxy)
except TypeError:
proxy = _StrongRef(func)
if proxy in self._func_cid_map[s]:
return self._func_cid_map[s][proxy]
cid = next(self._cid_gen)
self._func_cid_map[s][proxy] = cid
self.callbacks.setdefault(s, {})
self.callbacks[s][cid] = proxy
return cid
我正在寻找公共数据结构(不以_
开头的公共数据结构),而不是尝试阅读所有这些内容,以查看是否有可以查询的内容。看来CallbackRegistry.callbacks
是一本字典,它将事件名称映射到包含这些事件函数的某种形式的集合。
确实,可以通过以下方法来支持:
In [6]: fig.canvas.callbacks.callbacks
Out[6]:
{'button_press_event': {0: <weakref at 0x117bcff98; to 'FigureCanvasTkAgg' at 0x117c0f860>,
4: <matplotlib.cbook._StrongRef at 0x117c0f550>,
5: <matplotlib.cbook._StrongRef at 0x119686dd8>},
'scroll_event': {1: <weakref at 0x117be4048; to 'FigureCanvasTkAgg' at 0x117c0f860>},
'key_press_event': {2: <weakref at 0x117be43c8; to 'FigureManagerTk' at 0x117c0fe10>},
'motion_notify_event': {3: <weakref at 0x117be4438; to 'NavigationToolbar2Tk' at 0x117c0fe48>}}
有趣的是,在这种特殊情况下,我个人仅添加了一个事件处理程序(button_press_event
),但是显然我拥有的事件更多。在这里看到的实际上也是后端中正在运行的所有事件。是否曾经想过如何禁用其中一些功能(例如键盘快捷键)?这只是事件的字典,没有什么能阻止它们的发生:
# Delete / remove the keyboard press event handlers.
fig.canvas.callbacks.callbacks.pop('key_press_event')
如果您想获取对底层函数的引用,则进行一些自省可以建议您执行以下操作:
In [37]: for cid, func_ref in fig.canvas.callbacks.callbacks['button_press_event'].items():
...: func = func_ref()
...: print(cid, func)
Out[37]: 5 <function onclick at 0x114d7e620>