将matplotlib的鼠标按钮事件与pick事件结合起来 [英] Combining matplotlib's mouse button events with pick events
问题描述
基于鼠标按钮和按键事件的组合,将不同的功能应用于散点图的点.当按下鼠标左键时,matplotlib 的 Lasso 小部件被调用并具有包含的点功能1发生.按下 Shift + LMB
时,将绘制 Lasso
,并且功能2随包含的点而发生.当按下 Alt+LMB
时,会绘制一个 Lasso
并使用包含的点功能 3.最后但并非最不重要的是,当我按下 RMB
时,会触发一个选择事件,并给出散点图中所选点的索引.
Based on combination of mouse button and key events, different functionalities are applied to the points of a scatter plot. When the left mouse button is pressed matplotlib's Lasso widget is called and with the included points functionality 1 takes place. When Shift+LMB
are pressed a Lasso
is drawn and functionality 2 takes place with the included points. When Alt+LMB
are pressed a Lasso
is drawn and with the included points functionality 3 takes place. Last, but not least, when I press the RMB
a pick event is triggered and the index of the selected point in the scatter plot is given.
自从我添加了 pick
事件以来,上述功能可以正常工作,直到首次触发了 pick
事件.当它被触发时,画布似乎被锁定,我无法使用任何其他功能.虽然,我得到了所选点的索引,但没有出现任何错误,并且画布变得无响应.
Since I added the pick
event, the aforementioned functionalities work correctly until a pick
event is triggered for the first time. When it is triggered it seems that the canvas gets locked and I can not use any other functionality. Although, I get the index of the selected point, I do not get any errors, and the canvas becomes unresponsive.
我修改了从中获取的代码问题,这实际上是我想要做的.
I modified the code taken from this question, which is actually what I want to do.
代码:
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()
有关导致此故障的原因的任何建议?预先感谢.
Any suggestions on what might be causing this malfunction? Thanks in advance.
推荐答案
您这次遇到的问题是您同时拥有一个 PickEvent
和一个 MouseEvent
在您单击艺术家时同时生成. MouseEvent
锁定画布,并阻止您之后再执行其他任何操作.
The problem you're having this time is that you have both a PickEvent
and a MouseEvent
that are generated at the same time when you click on an artist. The MouseEvent
locks the canvas and prevents you from doing anything else afterward.
最好的解决方案是防止 MouseEvent
在 PickEvent
之后被触发,但我不知道是否有办法做到这一点.相反,我添加了一个测试来检查是否在 onpick()
之后调用了 onpress()
以禁用锁定机制.
The best solution would be to prevent the MouseEvent
from being fired after the PickEvent
, but I don't know if there's a way to do that. Instead, I added a test to check whether onpress()
was called after onpick()
to disable the locking mechanism.
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()
这篇关于将matplotlib的鼠标按钮事件与pick事件结合起来的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!