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()
I tried to use the figure.canvas.mpl_connect() in matplotlib to build an interactive plot in a panel, but failed. The code below works well without plotting on a panel. The difference is on a panle, the plt.show() cannot be used. Does figure.canvas.mpl_connect() work on wxpython? Or there are other ways to make interactive plot? Thanks!
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()
I run a mile when faced with plotting with matplotlib but I'm pretty sure you are meant to connect to the FigureCanvas
not the figure
thrown out by plt.subplots
, although I'm happy to be corrected, as I said, I'm an unhappy camper in the forest of matplotlib.
The result would be:
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()
Now click on a coloured dot.
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]