Matplotlib + wxPython - 如何将自定义事件作为matplotlib事件传递?

时间:2016-11-24 13:30:16

标签: python events matplotlib wxpython

我目前正在尝试在我的代码中实现自定义多点触控事件。我当前的代码是模块化的,并分成三个文件(Main.py,Panel1.py,Panel2.py),例如这里是一个最小的工作示例:

Panel1.py

import matplotlib
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.backends.backend_wx import NavigationToolbar2Wx
from matplotlib.figure import Figure

import wx
import numpy as np

class Panel1(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
        self.figure = Figure()
        self.axes = self.figure.add_subplot(111)
        self.canvas = FigureCanvas(self, -1, self.figure)

        t = np.arange(0.0, 3.0, 0.01)
        s = np.sin(2 * np.pi * t)
        self.axes.plot(t, s)

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
        self.SetSizer(self.sizer)
        self.Fit()

        self.canvas.mpl_connect('motion_notify_event', self.onHover)

    def onHover(self, event):

        x1 = event.xdata
        y1 = event.ydata

        if event.inaxes == self.axes:
            print "Browsing in Panel 1"

Panel2.py

import matplotlib
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.backends.backend_wx import NavigationToolbar2Wx
from matplotlib.figure import Figure

import wx
import numpy as np

class Panel2(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
        self.figure = Figure()
        self.axes = self.figure.add_subplot(111)
        self.canvas = FigureCanvas(self, -1, self.figure)

        t = np.arange(0.0, 3.0, 0.01)
        s = np.cos(2 * np.pi * t)
        self.axes.plot(t, s)

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
        self.SetSizer(self.sizer)
        self.Fit()

        self.canvas.mpl_connect('motion_notify_event', self.onHover)

    def onHover(self, event):

        x1 = event.xdata
        y1 = event.ydata

        if event.inaxes == self.axes:
            print "Browsing in Panel 2"

Main.py

import matplotlib
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.backends.backend_wx import NavigationToolbar2Wx
from matplotlib.figure import Figure

import wx
import numpy as np

import Panel1 as FirstPanel
import Panel2 as SecondPanel

#MultiTouchHoverEvent, EVT_MULTITOUCH_HOVER = wx.lib.newevent.NewEvent()

class MainFrame(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self, None, title="Main Frame", size=(600, 600))
        self.SetBackgroundColour('white')

        self.panel_size = (10,10)

        self.InitUI()
        self.Centre()
        self.Show()

    def InitUI(self):

        sizer = wx.GridBagSizer(10, 10)

        self.Panel1 = FirstPanel.Panel1(self)
        sizer.Add(self.Panel1, flag=wx.EXPAND, pos=(0, 0), span=(1, 1))

        self.Panel2 = SecondPanel.Panel2(self)
        sizer.Add(self.Panel2, flag=wx.EXPAND, pos=(0, 1), span=(1, 1))

        sizer.AddGrowableCol(0)
        sizer.AddGrowableCol(1)

        sizer.AddGrowableRow(0)


        #self.Bind(EVT_MULTITOUCH_HOVER, self.multitouch_handler)

        self.SetSizerAndFit(sizer)

if __name__ == '__main__':

    app = wx.App(False) 
    MainFrame()
    app.MainLoop()

现在我已经创建了这个自定义事件EVT_MULTITOUCH_HOVER,您可以在 Main.py 代码中看到注释掉的内容。我可以将它绑定到框架,并且当与我的多点触控代码结合使用时它可以成功运行。但是,我想要做的是让EVT_MULTITOUCH_HOVER覆盖matplotlib 'motion_notify_event'。这样,我可以在每个面板的onHover函数中分别为每个面板指定适当的操作

(Panel1.py, Panel2.py)

我不确定我是否已经解释得很好,所以请问你是否有任何问题。

自定义事件可以是任何内容,它不必像我的示例中那样是多点触控事件。但是,为了完整性,关于多点触控代码,我使用pytuio并在后台运行一个名为tongseng的tuio服务器,它通过tuio协议发送与我的mac上的多点触控板的交互。然后我有一个我创建的类,它运行一个单独的线程,不断监听tuio事件,然后处理信息并调用wx.PostEvent以获取适当的自定义事件(悬停,双击,鼠标释放等)。

0 个答案:

没有答案