本文介绍了使用 matplotlib 在 wxpython 面板中组合键和鼠标按钮事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

wxPython 面板中,我想使用 matplotlib's 套索 小部件.在我的实现中,Lasso 用于三种不同的功能.尽管如此,为了完成这些功能,我必须将按键事件与鼠标按钮事件结合起来.

In a wxPython panel I want to use matplotlib's Lasso widget. In my implementation Lasso is used in three different functionalities. Nevertheless, in order to accomplish these functionalities I must combine key events with mouse button events.

默认情况下,初始Lasso 功能可以通过按下鼠标左键来使用.因此,对于我的第一个功能,我按下鼠标左键,选择一个感兴趣的区域并使用包含的点执行一些操作.对于第二个功能,我想选择另一个感兴趣的区域并用这些点做其他事情.我试图通过按 shift+LMB 来做到这一点.最后,在我的第三个功能中,我想通过按 Ctrl+LMB 对选定的点执行其他操作.

By default, the initial Lasso function can be used by pressing the left mouse button. So, for my first functionality I press the left mouse button, select a region of interest and do something with the points included. For the second functionality, I would like to select another region of interest and do something else with these points.I am trying to do that by pressing shift+LMB. Finally, in my third functionality I would like to do something else with the selected points by pressing Ctrl+LMB.

示意性地,我想执行以下操作:

Schematically, I would like to do the following:

 if left mouse button is pressed:
    use Lasso and with the included points do the 1st functionality

 if shift is press and left mouse button is pressed:

   use Lasso and with the included points do the 2nd functionality

 if ctrl is press and lmb is also pressed :
    call Lasso and with the included points do the 3rd functionality

不幸的是,我无法实现我的目标,并且出现以下错误:if self.shift_is_held == True:AttributeError: 对象没有属性shift_is_held".它似乎无法识别按钮事件,而在其他情况下,widgetlock 命令似乎无法使轴可用.

Unfortunately, I can not achieve my goal and I get the following error: if self.shift_is_held == True:AttributeError: object has no attribute 'shift_is_held'. It seems that it can not recognize the button events, while in other cases the widgetlock command seems not to make the axes available.

这是我的部分代码:

def scatter(self,data):
#create scatter plot
    fig = self._view_frame.figure
    fig.clf()

    Data = []
    self.lmans = []
    self.points_colors = []

    Data2 = []
    self.lmans_2 = []

    Data3 = []
    self.lmans_2 = []


    ax = fig.add_subplot('111')

    datum = []
    datum_2 = []
    datum_3 = []

    for x,y in zip(self.data[:,0],self.data[:,1]):
        datum.append(Datum(x,y))
        datum_2.append(Datum2(x,y))
        datum_3.append(Datum3(x,y))


    ax.scatter(self.data[:, 0], self.data[:, 1], s=150, marker='d')
    ax.set_xlim((min(self.data[:,0]), max(self.data[:,0])))
    ax.set_ylim((min(self.data[:,1]), max(self.data[:,1])))
    ax.set_aspect('auto')

    Data.append(datum)
    Data2.append(datum_2)
    Data3.append(datum_3)
    lman = self.LassoManager(ax, datum, Data)
    lman_2 = self.LassoManager2(ax, datum_2, Data2)
    lman_3 = self.LassoManager3(ax, datum_3, Data3)
    fig.canvas.draw()
    self.lmans.append(lman)
    self.lmans_2.append(lman_2)
    self.lmans_3.append(lman_3)
    fig.canvas.mpl_connect('axes_enter_event', self.enter_axes)


class Lasso(AxesWidget):


"""Selection curve of an arbitrary shape.

The selected path can be used in conjunction with
:func:`~matplotlib.path.Path.contains_point` to select data points
from an image.

Unlike :class:`LassoSelector`, this must be initialized with a starting
point `xy`, and the `Lasso` events are destroyed upon release.

Parameters:

*ax* : :class:`~matplotlib.axes.Axes`
    The parent axes for the widget.
*xy* : array
    Coordinates of the start of the lasso.
*callback* : function
    Whenever the lasso is released, the `callback` function is called and
    passed the vertices of the selected path.

"""

def __init__(self, ax, xy, callback=None, useblit=True):
    AxesWidget.__init__(self, ax)

    self.useblit = useblit and self.canvas.supports_blit
    if self.useblit:
        self.background = self.canvas.copy_from_bbox(self.ax.bbox)

    x, y = xy
    self.verts = [(x, y)]
    self.line = Line2D([x], [y], linestyle='-', color='black', lw=2)
    self.ax.add_line(self.line)
    self.callback = callback
    self.connect_event('button_release_event', self.onrelease)
    self.connect_event('motion_notify_event', self.onmove)

def onrelease(self, event):
    if self.ignore(event):
        return
    if self.verts is not None:
        self.verts.append((event.xdata, event.ydata))
        if len(self.verts) > 2:
            self.callback(self.verts)
        self.ax.lines.remove(self.line)
    self.verts = None
    self.disconnect_events()

def onmove(self, event):
    if self.ignore(event):
        return
    if self.verts is None:
        return
    if event.inaxes != self.ax:
        return
    if event.button != 1:
        return
    self.verts.append((event.xdata, event.ydata))

    self.line.set_data(list(zip(*self.verts)))

    if self.useblit:
        self.canvas.restore_region(self.background)
        self.ax.draw_artist(self.line)
        self.canvas.blit(self.ax.bbox)
    else:
        self.canvas.draw_idle()

def enter_axes(self, event):
    self.idfig = event.inaxes.colNum
    self._view_frame.figure.canvas.mpl_connect('button_press_event', self.onpress_2)
    self._view_frame.figure.canvas.mpl_connect('key_press_event', self.onkey_press_2)
    self._view_frame.figure.canvas.mpl_connect('key_release_event', self.onkey_release_2)
    self._view_frame.figure.canvas.mpl_connect('button_press_event', self.onpress_3)
    self._view_frame.figure.canvas.mpl_connect('key_press_event', self.onkey_press_3)
    self._view_frame.figure.canvas.mpl_connect('key_release_event', self.onkey_release_3)

def LassoManager(self, ax, data, Data):
    self.axes = ax
    self.canvas = ax.figure.canvas
    self.data = data
    self.Data = Data
    self.Nxy = len(data)

    # self.facecolors = [d.color for d in data]
    self.xys = [(d.x, d.y) for d in data]
    fig = ax.figure
    #self.cid = self.canvas.mpl_connect('button_press_event', self.onpress)



def callback(self, verts):
    #facecolors = self.facecolors#collection.get_facecolors()
    #colorin = colorConverter.to_rgba('red')
    #colorout = colorConverter.to_rgba('blue')
    p = path.Path(verts)
    self.ind = p.contains_points([(d.x, d.y) for d in self.Data[self.where.colNum]])
    self._view_frame.figure.canvas.mpl_connect('button_press_event', self.onpress)

    #Functionality 1

    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)
        self.where = event.inaxes
        # acquire a lock on the widget drawing
        self.canvas.widgetlock(self.lasso)

   def onkey_press_2(self,event):
    if event.key =='shift':
        self.merge_is_held = True


def onkey_press_3(self,event):
    if event.key == 'control':
        self.split_is_held = True

def onkey_release_2(self, event):
       if event.key == 'shift':
           self.merge_is_held = False


def onkey_release_3(self, event):
   if event.key == 'control':
        self.split_is_held = False

def LassoManagerMerge(self, ax, data2, Data2):
    self.axes = ax
    self.canvas = ax.figure.canvas
    self.data2 = data2
    self.Data2 = Data2
    self.Nxy = len(dataMerge)

    self.facecolors_2 = [d.color for d in data2]
    # print "facecolors",self.facecolors
    self.xys = [(d.x, d.y) for d in data2]
    # print "xys",self.xys
    fig = ax.figure
    self.collection_2 = RegularPolyCollection(
        fig.dpi, 6, sizes=(0,),
        facecolors=self.facecolors_2,
        offsets = self.xys,
        transOffset = ax.transData)

    ax.add_collection(self.collection_2)





def callback_2(self, verts):

    self.facecolors_2 = self.collection_2.get_facecolors()
    #colorin = colorConverter.to_rgba('red')
    #colorout = colorConverter.to_rgba('blue')
    p = path.Path(verts)
    self.ind = p.contains_points([(d.x, d.y) for d in self.Data2[self.where.colNum]])
    #Functionality 2

    self.canvas.draw_idle()
    self.canvas.widgetlock.release(self.lasso_2)

    del self.lasso_2

 def onpress_2(self, event):


            if self.canvas.widgetlock.locked():  return
            if event.inaxes is None: return
            if event.button == 1:
               if self.shift_is_held == True:
                    print "Shift pressed"
                    self.lasso_2 = Lasso(event.inaxes, (event.xdata, event.ydata), self.callback_2)
                    print "Shift pressed"
                    self.where = event.inaxes
                    self.canvas.widgetlock(self.lasso_2)

              def LassoManager3(self, ax, data3, Data3):
    self.axes = ax
    self.canvas = ax.figure.canvas
    self.data3 = data3
    self.Data3 = Data3
    self.Nxy = len(data3)

    self.facecolors_3= [d.color for d in data3]
    # print "facecolors",self.facecolors
    self.xys = [(d.x, d.y) for d in data3]

    # print "xys",self.xys
    fig = ax.figure
    self.collection_3 = RegularPolyCollection(
        fig.dpi, 6, sizes=(0,),
        facecolors=self.facecolors_3,
        offsets = self.xys,
        transOffset = ax.transData)

    ax.add_collection(self.collection_3)



def callback_3(self, verts):
    self.facecolors_3 = self.collection_3.get_facecolors()
    #colorin = colorConverter.to_rgba('red')
    #colorout = colorConverter.to_rgba('blue')
    p = path.Path(verts)
    self.ind = p.contains_points([(d.x, d.y) for d in self.Data3[self.where.colNum]])

    #Functionality 3
    self.canvas.draw_idle()
    self.canvas.widgetlock.release(self.lasso_3)

    del self.lasso_3

def onpress_3(self, event):

            if self.canvas.widgetlock.locked(): return
            if event.inaxes is None: return
            if event.button == 1:
                if self.split_is_held == True:
                    print " Split pressed"
                    self.lasso_3 = Lasso(event.inaxes, (event.xdata, event.ydata), self.callback_3)
                    print "Split pressed"
                    self.where = event.inaxes
                    # acquire a lock on the widget drawing
                    self.canvas.widgetlock(self.lasso_3)

有什么建议吗?

推荐答案

我不完全确定您做错了什么,因为您的代码看起来不完整.我认为您的总体想法是正确的,但您似乎一直在混淆类并试图从错误的类或其他东西访问属性 shift_is_held.

I'm not entirely sure what you're doing wrong because your code looks incomplete. I think your general idea was correct, but you seem to have been mixing up classes and trying to access the property shift_is_held from the wrong class or something.

我使用 matplotlib 示例中的 lasso_example.py 代码编写了这个简单的示例.我在尝试使用 键时确实遇到了一些复杂情况.当我尝试使用控制键用鼠标拖动时,套索管理器变得无响应(包括来自 matplotlib 的原始代码).我不知道为什么,所以我在当前代码中使用 和 键作为修饰符.

I wrote this simple example using the lasso_example.py code from matplotlib examples. I did run into some complications trying to use the key. When I try to drag with the mouse using the control key, the Lasso manager becomes unresponsive (including in the original code from matplotlib). I could not figure out why, so I used the and keys as modifiers in the present code.

你会看到,在释放套索的那一刻,执行什么动作的逻辑是在LassoManager.callback()

You'll see that the logic of what action to perform depending on which key is held down at the moment when you release the lasso is performed in LassoManager.callback()

import logging
import matplotlib
from matplotlib.widgets import Lasso
from matplotlib.colors import colorConverter
from matplotlib.collections import RegularPolyCollection
from matplotlib import path

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.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
            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+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

if __name__ == '__main__':

    data = [Datum(*xy) for xy in rand(100, 2)]

    ax = plt.axes(xlim=(0,1), ylim=(0,1), autoscale_on=False)
    lman = LassoManager(ax, data)

    plt.show()

这篇关于使用 matplotlib 在 wxpython 面板中组合键和鼠标按钮事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-29 04:29