Javier
Javier

Reputation: 831

Embed multiple matplotlib figures in wxPython

I have a 2x2 FlexGridSizer in a panel and I want to insert four different matplotlib figures with their own toolbars at the same time.

I have seen many links related and working examples embedding one figure, but as I am a begginer with wxPython and OOP I get quite confuse when testing some codes and trying to merge them with mine.

Here is a piece of the page class of a wx.Notebook where I want to put the figures

class Pagina(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)

        self.boton_descargar = wx.Button(self, -1, label=u"Descargar")
        self.boton_desconectar = wx.Button(self, -1, label=u"Desconectar")

        sizer = wx.BoxSizer(wx.VERTICAL)
        subsizer1 = wx.BoxSizer(wx.HORIZONTAL)
        subsizer2 = wx.FlexGridSizer(rows=2, cols=2)

        sizer.Add(subsizer1, 0, wx.EXPAND | wx.ALL, 0)
        sizer.Add(subsizer2, 1, wx.EXPAND | wx.ALL, 0)
        sizer.Add(self.boton_desconectar, 0, wx.ALIGN_RIGHT | wx.RIGHT, 10)
        subsizer1.Add(self.boton_descargar, 0, wx.ALL, 10)

        self.Bind(wx.EVT_BUTTON, self.onClick_descargar, self.boton_descargar)
        self.Bind(wx.EVT_BUTTON, self.onClick_desconectar, self.boton_desconectar)

        self.SetSizer(sizer)

    def onClick_descargar(self, event):
        HiloDescarga()

    def onClick_desconectar(self, event):
        pass

HiloDescarga is actually a thread launched to download some text lines, process data and plotting this way (the fourth figure is the same thing):

import matplotlib.pyplot as plt

line, = plt.plot(range(len(x)), x, '-', linewidth=1)
line, = plt.plot(range(len(x)), f, 'y-', linewidth=1)
plt.xlabel('x')
plt.ylabel('y')
plt.title(r'title1')
plt.grid()
plt.figure()

line, = plt.plot(range(len(y)), y, 'r-', linewidth=1)
line, = plt.plot(range(len(y)), g, 'y-', linewidth=1)
plt.xlabel('x')
plt.ylabel('y')
plt.title(r'title2')
plt.grid()
plt.figure()

line, = plt.plot(range(len(z)), z, 'g-', linewidth=1)
line, = plt.plot(range(len(z)), h, 'y-', linewidth=1)
plt.xlabel('x')
plt.ylabel('y')
plt.title(r'title3')
plt.grid()

plt.show()

so the figures are just popping in separated windows. If you could give me a snippet or at least some orientation, perhaps a few changes to the plotting code, I don't know. Any help is welcomed.

Upvotes: 0

Views: 737

Answers (1)

Diziet Asahi
Diziet Asahi

Reputation: 40747

You just have to follow the examples where they embed one Figure, but instead instantiate several members for each of the figures you want to create. Here is a quick example:

import matplotlib
matplotlib.use('WXAgg')
from matplotlib.figure import Figure
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
import wx


class MyFrame(wx.Frame):
    def __init__(self, parent, nbFigures=4):
        super(MyFrame, self).__init__(parent)
        sizer = wx.BoxSizer(wx.VERTICAL)
        self.figs = [Figure(figsize=(2,1)) for _ in range(nbFigures)]
        self.axes = [fig.add_subplot(111) for fig in self.figs]
        self.canvases = [FigureCanvas(self, -1, fig) for fig in self.figs]
        for canvas in self.canvases:
            sizer.Add(canvas, 0, wx.ALL, 5)
        self.SetSizer(sizer)

app = wx.App()
frm = MyFrame(None)
frm.Show()
app.MainLoop()

enter image description here

I've saved the instances of each figure in the array self.figs and each instances of the axes on each figure in self.axes

Hope that puts you in the right tracks

Upvotes: 2

Related Questions