Wx Matplotlib事件处理



我正在开发WX-MPL应用程序,以根据用户输入显示和交互处理数据。我在设置MPL鼠标事件以在WX应用程序中工作时遇到困难。

目标是拥有一系列可编辑的垂直线,这些线描绘了在早期处理中识别的特征的开始和结束时间。用户应该能够沿着x轴拖动线,删除不需要的线,并插入新行。

到目前为止,我已经能够使用标准的MPL绘图图(我认为它是Tk)来实现这一功能。当我试图将这些类集成到我的应用程序中时,事件处理出现了问题,我无法与行对象交互或创建新的行对象。因此,我备份了一个步骤,并一直试图将复杂性添加到我的工作示例中,以确定问题出现的位置。

当将工作示例作为简单的WX应用程序运行时,NewVLineListener类似乎不再接收button_press_events。以下是与我遇到的特定问题相关的代码。

这是我第一次处理鼠标事件,我肯定错过了一些东西。。。如有任何建议,我们将不胜感激。

此外,我正在运行WX 2.8.12和MPL 1.1.1rc。

from matplotlib.figure import Figure
import wx
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
class NewVLineListener:
    global castLog, count, dvls, ax1
    lock = None  # only one can be animated at a time
    def __init__(self, fig):
        self.fig = fig
    def connect(self):
        'connect to all the events we need'
        self.cidpressright = self.fig.canvas.mpl_connect(
        'button_press_event', self.on_press_right)
    def on_press_right(self, event):
        global count, castLog, dvls, ax1
        print event.button
        if event.button != 3: return
        tag = 'Begin'
        # Increase castLog Key to accomodate new Vline
        count += 1
        print 'count: ', count
        # Set castLog values to x-value of triggering event
        castLog[str(count)] = { tag:event.xdata }
        # Spawn a new DraggableVline instance
        color_map = {'Begin':'g', 'End':'r'}
        dvl = DraggableVline(self.fig, ax1.axvline(x=castLog[str(count)][tag], linewidth=2, color=color_map[tag]), count, tag)
        dvl.connect()
        dvls.append(dvl)
        canvas = self.fig.canvas
        canvas.draw()
class MainFrame(wx.Frame):
        def __init__(self):
            wx.Frame.__init__(self, None, wx.ID_ANY)
            global castLog, count, ax1, dvls
            fig = Figure()
            canvas = FigureCanvasWxAgg(self, -1, fig)
            ax1 = fig.add_subplot(111)
            # Create empty dict that will hold new V-line Data
            castLog = { } 
            dvls = [ ]
            count = 0
            # Instantiate New Vline Listener
            NVL = NewVLineListener(fig)
            NVL.connect()
if __name__ == '__main__':
        app = wx.PySimpleApp()
        app.frame = MainFrame()
        app.frame.Show()
        app.MainLoop()

我搞定了!

我认为对NewVlineListener对象的引用是垃圾收集的,因此从未接收到事件。通过将NVL对象引用添加到可拖动vline对象的引用数组中,它可以保持不变并按预期接收事件。

class MainFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY)
        global castLog, count, ax1, dvls
        fig = Figure()
        canvas = FigureCanvasWxAgg(self, -1, fig)
        ax1 = fig.add_subplot(111)
        # Create empty dict that will hold new V-line Data
        castLog = { } 
        dvls = [ ]
        count = 0
        # Instantiate New Vline Listener
        NVL = NewVLineListener(fig)
        NVL.connect()
        dvls.append(NVL) # This keeps NVL reference from being garbage collected?

我仍然觉得有趣的是,命名NewVlineListener对象不足以保留引用,而且它在pyplot中运行良好,但现在在wx中运行良好。

最新更新