2

I am trying to use MatPlotLib with WXPython. I find a nice example from http://www.cs.colorado.edu/~kena/classes/5448/s11/presentations/pearse.pdf because it show how to use 2 panels and it is well explained how to embed matplotlib. But I think it is missing some part, because the graphic isn't being initialized. How can I fix that?

import wx
import numpy
import matplotlib
from matplotlib.figure import Figure
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas

class TestFrame(wx.Frame):
    def __init__(self,parent,title):
        wx.Frame.__init__(self,parent,title=title,size=(500,500))
        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)
        self.sp.SplitVertically(self.p1,self.p2,100)
        self.statusbar = self.CreateStatusBar()
        self.statusbar.SetStatusText('Oi')

class p1(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent,-1,size=(50,50))

        self.figure = matplotlib.figure.Figure()
        self.axes = self.figure.add_subplot(111)
        t = numpy.arange(0.0,10,1.0)
        s = [0,1,0,1,0,2,1,2,1,0]
        self.y_max = 1.0
        self.axes,plot(t,s)
        self.canvas = FigureCanvas(self,-1,self.figure)

app = wx.App(redirect=False)
frame = TestFrame(None, 'Hello World!')
frame.Show()
app.MainLoop()

Thanks.

furas
  • 134,197
  • 12
  • 106
  • 148
Zhozer
  • 125
  • 1
  • 5

1 Answers1

2

You made class p1 with matplot but you didn't use it in TestFrame.

I changed some names to make it more clear

import wx
import numpy 
import matplotlib

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

class TestFrame(wx.Frame):
    def __init__(self,parent,title):
        wx.Frame.__init__(self,parent,title=title,size=(500,500))
        self.sp = wx.SplitterWindow(self)
        self.p1 = wx.Panel(self.sp, style=wx.SUNKEN_BORDER)
        self.p2 = MatplotPanel(self.sp)
        self.sp.SplitVertically(self.p1,self.p2,100)
        self.statusbar = self.CreateStatusBar()
        self.statusbar.SetStatusText('Oi')

class MatplotPanel(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent,-1,size=(50,50))

        self.figure = Figure()
        self.axes = self.figure.add_subplot(111)
        t = numpy.arange(0.0,10,1.0)
        s = [0,1,0,1,0,2,1,2,1,0]
        self.y_max = 1.0
        self.axes.plot(t,s)
        self.canvas = FigureCanvas(self,-1,self.figure)

app = wx.App(redirect=False)
frame = TestFrame(None, 'Hello World!')
frame.Show()
app.MainLoop()

see also (as example) my answer to how to combine wxPython, matplotlib and Pyopengl

EDIT:

MatplotPanel with NavigationToolbar and wx.Button to change plot.

EDIT: 2022.01.03

As @Samuel said in comment: newer matplotlib needs NavigationToolbar2WxAgg instead of NavigationToolbar2Wx. See also matplotlib doc: Embedding in wx #2

# older matplotlib
#from matplotlib.backends.backend_wxagg import NavigationToolbar2Wx as NavigationToolbar

# newer matplotlib 
from matplotlib.backends.backend_wxagg import NavigationToolbar2WxAgg as NavigationToolbar

class MatplotPanel(wx.Panel):
    
    def __init__(self, parent):     
        wx.Panel.__init__(self, parent,-1,size=(50,50))

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(self.sizer)
        
        self.figure = Figure()
        self.axes = self.figure.add_subplot(111)
        self.canvas = FigureCanvas(self, -1, self.figure)
        self.toolbar = NavigationToolbar(self.canvas)

        self.button = wx.Button(self, -1, "Change plot")
        self.button.Bind(wx.EVT_BUTTON, self.changePlot)
        
        self.sizer.Add(self.toolbar, 0, wx.EXPAND)
        self.sizer.Add(self.button, 0, wx.EXPAND)
        self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
        
        self.drawSin()
        self.current_draw = 'sin'
        
#       self.drawLines()

    def changePlot(self, event):
        
        if self.current_draw == 'sin' :
            self.drawLines()
            self.current_draw = 'lines'
        else: 
            self.drawSin()
            self.current_draw = 'sin'
            
        self.Layout()
        
    def drawLines(self):
    
        x = numpy.arange(0.0,10,1.0)
        y = [0,1,0,1,0,2,1,2,1,0]
        
        self.axes.clear()
        self.axes.plot(x, y)

    def drawSin(self):
    
        x = numpy.arange(0.0,10,0.1)
        y = numpy.sin(x)
        
        self.axes.clear()
        self.axes.plot(x, y)

furas
  • 134,197
  • 12
  • 106
  • 148
  • Thanks @furas. I am new to Matplotlib and WxPython. How can I put the box with Home/Subplot/Zoom etc in this program? Normally it is automatically. – Zhozer Nov 11 '13 at 20:54
  • I add example with navigation toolbar. – furas Nov 11 '13 at 21:44
  • I add `wx.Button` to change plot – furas Nov 11 '13 at 22:02
  • Wow, nice, @furas. But for me the button is with problem. When I click nothing happens, but sometimes when I click to the Pan button first than it changes to line (but not vice-versa). – Zhozer Nov 12 '13 at 01:21
  • Add "Agg" to "NavigationToolbar2Wx" on the import line to fix an error with newer versions of matplotlib. – Samuel Jan 02 '22 at 23:00
  • @Samuel thanks, I added it to answer and to code – furas Jan 03 '22 at 22:02