【问题标题】:Combining matplotlib's mouse button events with pick events将matplotlib的鼠标按钮事件与pick事件结合起来
【发布时间】:2015-09-07 19:09:27
【问题描述】:

基于鼠标按钮和按键事件的组合,不同的功能应用于散点图的点。当按下鼠标左键时,matplotlib 的 Lasso 小部件被调用,并且包含点功能 1 发生。当Shift+LMB 被按下时,Lasso 被绘制并且功能 2 发生在包含的点上。当Alt+LMB 被按下时,一个Lasso 被绘制并且包含点功能3 发生。最后但并非最不重要的一点是,当我按下RMB 时,将触发一个拾取事件,并给出散点图中所选点的索引。

自从我添加了pick 事件后,上述功能都可以正常工作,直到pick 事件第一次被触发。当它被触发时,画布似乎被锁定,我无法使用任何其他功能。虽然,我得到了所选点的索引,但我没有收到任何错误,并且画布变得无响应。

我修改了取自this问题的代码,这实际上是我想做的。

代码:

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()

关于可能导致此故障的任何建议?提前致谢。

【问题讨论】:

    标签: python matplotlib widget scatter-plot


    【解决方案1】:

    这次您遇到的问题是,当您点击某个艺术家时,您会同时生成 PickEventMouseEventMouseEvent 锁定画布并阻止您之后执行任何其他操作。

    最好的解决方案是防止MouseEventPickEvent 之后被解雇,但我不知道是否有办法做到这一点。相反,我添加了一个测试来检查 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()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-08
      • 1970-01-01
      • 2020-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多