1

I am attempting to have two matplotlib figures side-by-side inside a panel in a wxPython application. This used to work with wxPython 2.8, but no longer in wxPython 3.0.

In wxPython 2.8, the width of each plot is half of the panel size. In wxPython 3.0, the width of the plot is equal to the panel size, which means only the plot on the left shows. Expanding the window then eventually reveals the right-hand-side plot.

Simplest example that reproduces the problem is below.

import wx
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
from matplotlib.figure import Figure

class MainFrame(wx.Frame):
    def __init__(self, *args, **kwargs):
        wx.Frame.__init__(self, *args, **kwargs)

        panel = wx.Panel(self)
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(TestPlot(panel), 1, wx.EXPAND | wx.ALL, border=5)
        sizer.Add(TestPlot(panel), 1, wx.EXPAND | wx.ALL, border=5)
        panel.SetSizerAndFit(sizer)

class TestPlot(wx.Window):
    def __init__(self, *args, **kwargs):
        wx.Window.__init__(self, *args, **kwargs)

        self.canvas = FigureCanvasWxAgg(self, wx.ID_ANY, Figure())

        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(self.canvas, 1, wx.ALL, border=20)
        self.SetSizerAndFit(sizer)

if __name__ == "__main__":
    app = wx.App()
    MainFrame(parent=None, size=(300, 300)).Show()
    app.MainLoop()

How can I get this layout to work in wxPython 3.0?

1
  • I don't know the wx framework at all, but from what you describe and code smells I am guessing that the problem is that wx changed how it deals with sizer.Add(TestPlot(panel), 1, wx.EXPAND | wx.ALL, border=5) Commented Jan 11, 2015 at 0:46

2 Answers 2

1

I've had the same problem on wxpython 3.0.

I think the problem is that the default minimum size of self.canvas is too large.

Setting the minimum size manually to some very small values by self.canvas.SetMinSize(wx.Size(1,1)) seems to solve the problem. Not an elegant way though...

Following is the fixed version of your example.

import wx
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
from matplotlib.figure import Figure

class MainFrame(wx.Frame):
    def __init__(self, *args, **kwargs):
        wx.Frame.__init__(self, *args, **kwargs)

        panel = wx.Panel(self)
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(TestPlot(panel), 1, wx.EXPAND | wx.ALL, border=5)
        sizer.Add(TestPlot(panel), 1, wx.EXPAND | wx.ALL, border=5)
        panel.SetSizer(sizer)
        # don't do Fit(), as it sets the canvases to its minimum size
        panel.Layout()

class TestPlot(wx.Window):
    def __init__(self, *args, **kwargs):
        wx.Window.__init__(self, *args, **kwargs)

        self.canvas = FigureCanvasWxAgg(self, wx.ID_ANY, Figure())
        # setting the minimum canvas size as small as possible
        self.canvas.SetMinSize(wx.Size(1,1))

        sizer = wx.BoxSizer(wx.HORIZONTAL)
        # added wx.EXPAND so that the canvas can stretch vertically
        sizer.Add(self.canvas, 1, wx.ALL|wx.EXPAND, border=20)
        self.SetSizer(sizer)

if __name__ == "__main__":
    app = wx.App()
    MainFrame(parent=None, size=(300, 300)).Show()
    app.MainLoop()

Hope this helps.

Tested on Windows 8.1/Python 2.7.9/matplotlib 1.4.3/wxpython 3.0.0.0

Sign up to request clarification or add additional context in comments.

Comments

0

Replace

    panel.SetSizerAndFit(sizer)

by

    panel.SetSizer(sizer)
    sizer.Fit(self)

to finally adjust the wx.Frame to the elements in the panel.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.