wxpython figure.canvas.mpl_connect() 不适用于交互式绘图

wxpython figure.canvas.mpl_connect() not work for interactive plot

import wx
import matplotlib.pyplot as plt
import numpy as np
from numpy.random import rand
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.backends.backend_wx import NavigationToolbar2Wx
from matplotlib.figure import Figure


class CanvasPanel(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
        self.figure, self.ax = plt.subplots()
        self.x, self.y, self.c, self.s = rand(4, 100)
        self.ax.scatter(self.x, self.y, 100 * self.s, self.c, picker=True)
        self.figure.canvas.mpl_connect('pick_event', self.onpick3)
        # plt.show()


        self.canvas = FigureCanvas(self, -1, self.figure)
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.canvas, 1, wx.RIGHT | wx.GROW)
        self.SetSizerAndFit(self.sizer)

    def onpick3(self, event):
        ind = event.ind
        print('onpick3 scatter:', ind, np.take(self.x, ind), np.take(self.y, ind))


class BetaFrame(wx.Frame):

    def __init__(self, parent, title):
        super().__init__(parent, -1, title=title, size=(1000, 1000),
                         style=wx.MINIMIZE_BOX | wx.RESIZE_BORDER | wx.SYSTEM_MENU |
                               wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN)

        self.initpos = 300
        self.sp = wx.SplitterWindow(self)
        self.p1 = wx.Panel(self.sp, style=wx.SUNKEN_BORDER)
        self.p2 = wx.Panel(self.sp, style=wx.SUNKEN_BORDER, name='Plot')
        self.p1.SetBackgroundColour('light')
        self.p2.SetBackgroundColour('light')
        self.sp.SplitVertically(self.p1, self.p2, self.initpos)
        self.Centre()

        CanvasPanel(self.p2)

if __name__ == '__main__':
    app = wx.App()
    frame = BetaFrame(None, 'Beta Version')
    frame.Show()
    app.SetTopWindow(frame)
    app.MainLoop()

我尝试使用 matplotlib 中的 figure.canvas.mpl_connect() 在面板中构建交互式绘图,但失败了。下面的代码无需在面板上绘制即​​可运行良好。不同之处在于面板上,plt.show() 不能使用。 figure.canvas.mpl_connect() 是否适用于 wxpython?还是有其他方法可以制作互动情节?谢谢!

import numpy as np
from numpy.random import rand
import matplotlib.pyplot as plt

class CanvasPanel:
    def __init__(self):
        # self.figure = Figure()
        self.figure, self.ax = plt.subplots()
        self.x, self.y, self.c, self.s = rand(4, 100)
        self.ax.scatter(self.x, self.y, 100 * self.s, self.c, picker=True)
        self.figure.canvas.mpl_connect('pick_event', self.onpick3)
        plt.show()

    def onpick3(self, event):
        ind = event.ind
        print('onpick3 scatter:', ind, np.take(self.x, ind), np.take(self.y, ind))
        
CanvasPanel()

我 运行 面对使用 matplotlib 进行绘图时,我走了一英里,但我很确定您要连接到 FigureCanvas 而不是 plt.subplots 抛出的 figure =],虽然我很高兴被纠正,正如我所说,我是 matplotlib 森林中的一个不快乐的露营者。

结果将是:

import wx
import matplotlib.pyplot as plt
import numpy as np
from numpy.random import rand
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.backends.backend_wx import NavigationToolbar2Wx
from matplotlib.figure import Figure


class CanvasPanel(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
        self.figure, self.ax = plt.subplots()
        self.x, self.y, self.c, self.s = rand(4, 100)
        self.ax.scatter(self.x, self.y, 100 * self.s, self.c, picker=True)
        # plt.show()


        self.canvas = FigureCanvas(self, -1, self.figure)
        self.canvas.mpl_connect('pick_event', self.onpick3)
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.canvas, 1, wx.RIGHT | wx.GROW)
        self.SetSizerAndFit(self.sizer)

    def onpick3(self, event):
        ind = event.ind
        print('onpick3 scatter:', ind, np.take(self.x, ind), np.take(self.y, ind))


class BetaFrame(wx.Frame):

    def __init__(self, parent, title):
        super().__init__(parent, -1, title=title, size=(1000, 1000),
                         style=wx.MINIMIZE_BOX | wx.RESIZE_BORDER | wx.SYSTEM_MENU |
                               wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN)

        self.initpos = 300
        self.sp = wx.SplitterWindow(self)
        self.p1 = wx.Panel(self.sp, style=wx.SUNKEN_BORDER)
        self.p2 = wx.Panel(self.sp, style=wx.SUNKEN_BORDER, name='Plot')
        self.p1.SetBackgroundColour('light')
        self.p2.SetBackgroundColour('light')
        self.sp.SplitVertically(self.p1, self.p2, self.initpos)
        self.Centre()

        CanvasPanel(self.p2)

if __name__ == '__main__':
    app = wx.App()
    frame = BetaFrame(None, 'Beta Version')
    frame.Show()
    app.SetTopWindow(frame)
    app.MainLoop()

现在点击彩色圆点。

onpick3 scatter: [7] [0.18704031] [0.43573093]
onpick3 scatter: [11] [0.19506781] [0.79896204]
onpick3 scatter: [71] [0.80362554] [0.9426998]
onpick3 scatter: [40 41] [0.78295576 0.76609123] [0.92129472 0.94352157]
onpick3 scatter: [40] [0.78295576] [0.92129472]
onpick3 scatter: [94] [0.94643354] [0.0547319]
onpick3 scatter: [26 37] [0.73187773 0.73352872] [0.01974885 0.05060254]

我已经包含了一个全面的 wxPython/matplotlib 与 wxGlade 的集成示例。 看这里:https://github.com/wxGlade/wxGlade/tree/master/examples/matplotlib3

正如 Rolf 所写,这条线连接 canvas:

self.canvas.mpl_connect( 'pick_event', self.on_pick)