基于鼠标按钮和键事件的组合,对散点图的点应用不同的功能。当按下鼠标左键时,调用matplotlib的Lasso小部件,并使用包含的点功能1。当Shift+LMB
被按下时,一个Lasso
被绘制出来,功能2在包含的点上发生。当Alt+LMB
被按下时,Lasso
被绘制,并与包含点功能3发生。最后,但并非最不重要的是,当我按下RMB
时,会触发一个拾取事件,并给出散点图中选定点的索引。
由于我添加了pick
事件,上述功能可以正常工作,直到第一次为触发pick
事件。当它被触发时,似乎画布被锁定,我不能使用任何其他功能。虽然,我得到了选定点的索引,但我没有得到任何错误,并且画布变得无响应。
我修改了取自这个问题的代码,这实际上是我想要做的。
代码:
import logging
import matplotlib
from matplotlib.widgets import Lasso
from matplotlib.colors import colorConverter
from matplotlib.collections import RegularPolyCollection
from matplotlib import path
import numpy as np
import matplotlib.pyplot as plt
from numpy.random import rand
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
class Datum(object):
colorin = colorConverter.to_rgba('red')
colorShift = colorConverter.to_rgba('cyan')
colorCtrl = colorConverter.to_rgba('pink')
colorout = colorConverter.to_rgba('blue')
def __init__(self, x, y, include=False):
self.x = x
self.y = y
if include:
self.color = self.colorin
else:
self.color = self.colorout
class LassoManager(object):
def __init__(self, ax, data):
self.axes = ax
self.canvas = ax.figure.canvas
self.data = data
self.Nxy = len(data)
facecolors = [d.color for d in data]
self.xys = [(d.x, d.y) for d in data]
fig = ax.figure
self.collection = RegularPolyCollection(fig.dpi, 6, sizes=(100,),facecolors=facecolors, offsets = self.xys, transOffset = ax.transData)
ax.add_collection(self.collection)
self.pick=self.canvas.mpl_connect('pick_event', self.onpick)
self.cid = self.canvas.mpl_connect('button_press_event', self.onpress)
self.keyPress = self.canvas.mpl_connect('key_press_event', self.onKeyPress)
self.keyRelease = self.canvas.mpl_connect('key_release_event', self.onKeyRelease)
self.lasso = None
self.shiftKey = False
self.ctrlKey = False
def callback(self, verts):
logging.debug('in LassoManager.callback(). Shift: %s, Ctrl: %s' % (self.shiftKey, self.ctrlKey))
facecolors = self.collection.get_facecolors()
p = path.Path(verts)
ind = p.contains_points(self.xys)
for i in range(len(self.xys)):
if ind[i]:
if self.shiftKey:
facecolors[i] = Datum.colorShift
elif self.ctrlKey:
facecolors[i] = Datum.colorCtrl
else:
facecolors[i] = Datum.colorin
print self.xys[i]
else:
facecolors[i] = Datum.colorout
self.canvas.draw_idle()
self.canvas.widgetlock.release(self.lasso)
del self.lasso
def onpress(self, event):
if self.canvas.widgetlock.locked(): return
if event.inaxes is None: return
self.lasso = Lasso(event.inaxes, (event.xdata, event.ydata), self.callback)
# acquire a lock on the widget drawing
self.canvas.widgetlock(self.lasso)
def onKeyPress(self, event):
logging.debug('in LassoManager.onKeyPress(). Event received: %s (key: %s)' % (event, event.key))
if event.key == 'alt':
self.ctrlKey = True
if event.key == 'shift':
self.shiftKey = True
def onKeyRelease(self, event):
logging.debug('in LassoManager.onKeyRelease(). Event received: %s (key: %s)' % (event, event.key))
if event.key == 'alt':
self.ctrlKey = False
if event.key == 'shift':
self.shiftKey = False
def onpick(self,event):
if event.mouseevent.button == 3:
index = event.ind
print('onpick scatter:', index, np.take(x, index), np.take(y, index))
if __name__ == '__main__':
x,y =rand(2,100)
data = [Datum(*xy) for xy in zip(x,y)]
fig = plt.figure()
ax = plt.axes()
ax.scatter(x,y,picker=True)
lman = LassoManager(ax, data)
plt.show()
有什么建议可能导致这个故障吗?
你这次遇到的问题是,当你点击一个艺术家时,你同时生成了一个PickEvent
和一个MouseEvent
。MouseEvent
锁定画布,并阻止您在之后执行任何其他操作。
MouseEvent
在PickEvent
之后被解雇,但我不知道是否有办法做到这一点。相反,我添加了一个测试来检查onpress()
是否在onpick()
之后被调用以禁用锁定机制。
import logging
import matplotlib
from matplotlib.widgets import Lasso
from matplotlib.colors import colorConverter
from matplotlib.collections import RegularPolyCollection
from matplotlib import path
import numpy as np
import matplotlib.pyplot as plt
from numpy.random import rand
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
class Datum(object):
colorin = colorConverter.to_rgba('red')
colorShift = colorConverter.to_rgba('cyan')
colorCtrl = colorConverter.to_rgba('pink')
colorout = colorConverter.to_rgba('blue')
def __init__(self, x, y, include=False):
self.x = x
self.y = y
if include:
self.color = self.colorin
else:
self.color = self.colorout
class LassoManager(object):
def __init__(self, ax, data):
self.axes = ax
self.canvas = ax.figure.canvas
self.data = data
self.Nxy = len(data)
facecolors = [d.color for d in data]
self.xys = [(d.x, d.y) for d in data]
fig = ax.figure
self.collection = RegularPolyCollection(fig.dpi, 6, sizes=(100,),facecolors=facecolors, offsets = self.xys, transOffset = ax.transData)
ax.add_collection(self.collection)
self.cid = self.canvas.mpl_connect('button_press_event', self.onpress)
self.keyPress = self.canvas.mpl_connect('key_press_event', self.onKeyPress)
self.keyRelease = self.canvas.mpl_connect('key_release_event', self.onKeyRelease)
self.pick=self.canvas.mpl_connect('pick_event', self.onpick)
self.lasso = None
self.shiftKey = False
self.ctrlKey = False
self.pickEvent = False
def callback(self, verts):
logging.debug('in LassoManager.callback(). Shift: %s, Ctrl: %s' % (self.shiftKey, self.ctrlKey))
facecolors = self.collection.get_facecolors()
p = path.Path(verts)
ind = p.contains_points(self.xys)
for i in range(len(self.xys)):
if ind[i]:
if self.shiftKey:
facecolors[i] = Datum.colorShift
elif self.ctrlKey:
facecolors[i] = Datum.colorCtrl
else:
facecolors[i] = Datum.colorin
print self.xys[i]
else:
facecolors[i] = Datum.colorout
self.canvas.draw_idle()
self.canvas.widgetlock.release(self.lasso)
del self.lasso
def onpress(self, event):
logging.debug('in LassoManager.onpress(). Event received: %s' % event)
if self.pickEvent:
self.pickEvent = False
return
if self.canvas.widgetlock.locked(): return
if event.inaxes is None: return
self.lasso = Lasso(event.inaxes, (event.xdata, event.ydata), self.callback)
# acquire a lock on the widget drawing
self.canvas.widgetlock(self.lasso)
def onKeyPress(self, event):
logging.debug('in LassoManager.onKeyPress(). Event received: %s (key: %s)' % (event, event.key))
if event.key == 'alt':
self.ctrlKey = True
if event.key == 'shift':
self.shiftKey = True
def onKeyRelease(self, event):
logging.debug('in LassoManager.onKeyRelease(). Event received: %s (key: %s)' % (event, event.key))
if event.key == 'alt':
self.ctrlKey = False
if event.key == 'shift':
self.shiftKey = False
def onpick(self, event):
logging.debug('in LassoManager.onpick(). Event received: %s' % event)
self.pickEvent = True
if event.mouseevent.button == 3:
index = event.ind
print 'onpick scatter: ', index, np.take(x, index), np.take(y, index)
if __name__ == '__main__':
x,y =rand(2,100)
data = [Datum(*xy) for xy in zip(x,y)]
fig = plt.figure()
ax = plt.axes()
ax.scatter(x,y,picker=True)
lman = LassoManager(ax, data)
plt.show()