这里有一种方法可以做到这一点,而不涉及特定的后端(即它应该是可移植的)。这个想法是matplotlib为后端实现定义了一个模糊的接口。此接口是类
NavigationToolbar2
下面(
github source
; 可能的linux源目录:/usr/lib/python3/dist-packages/matplotlib/backend_bases.py)。此接口使用
_nav_stack
类型的对象
Stack
从…起
cbook
。此堆栈保存有关不同平移信息的信息,当发生变化时,工具栏调用函数
_update_view
并重新绘制画布。通过创建我们自己的
堆栈
,将其提供(代理)到工具栏,并覆盖
_更新视图(_V)
,我们可以让工具栏做我们想做的事情。
import matplotlib.backend_bases
import matplotlib.pyplot as plt
from numpy.random import random
# this is the data structure is used by NavigationToolbar2
# to switch between different pans. We'll make the figure's
# toolbar hold a proxy to such an object
from matplotlib.cbook import Stack
class StackProxy:
def __init__(self,stack):
self._stack = stack
def __call__(self):
return self._stack.__call__()
def __len__(self):
return self._stack.__len__()
def __getitem__(self,ind):
return self._stack.__getitem__(ind)
def nop(self): pass
# prevent modifying the stack
def __getattribute__(self,name):
if name == '_stack':
return object.__getattribute__(self,'_stack')
if name in ['push','clear','remove']:
return object.__getattribute__(self,'nop')
else:
return object.__getattribute__(self._stack,name)
stack = Stack()
for data in [[random(10),random(10)] for _ in range(5)]:
stack.push(data)
def redraw(*args):
plt.clf()
plt.scatter(*stack()) # stack() returns the currently pointed to item
plt.gcf().canvas.draw()
fig = plt.gcf()
toolbar = fig.canvas.toolbar
toolbar._update_view = redraw.__get__(toolbar)
stackProxy = StackProxy(stack)
toolbar._nav_stack = stackProxy
redraw()
plt.show()
之前,我在修改按钮的一些基类,但从那时起,我了解了python的一些面向对象技术,并发现这是一个更好的解决方案。