Search code examples
pythonwxpythonwxwidgets

Multiple panels with BoxSizer


I m trying to divide a single panel into two panels. So Button1 should be in one panel abd Button 2 , 3, 4 should be on another panel.

Here is my runnable code which does not display the panels correctly.

import wx
from numpy import arange, sin, pi
import matplotlib
matplotlib.use('WXAgg')

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


class Frame1(wx.Frame):

    def __init__(self, parent):

        wx.Frame.__init__(self, None,
                          pos=wx.Point(0, 0),size=wx.Size(800, 200),
                          style=wx.DEFAULT_FRAME_STYLE | wx.MAXIMIZE )

        self.panel1 = wx.Panel(self)
        self.panel2 = wx.Panel(self)
        #self.panel1.SetBackgroundColour('blue')
        self.panel3 = wx.Panel(self)
        self.panel4 = wx.Panel(self)
        self.panel3.SetBackgroundColour('red')


        sizer1 = wx.BoxSizer(wx.VERTICAL)
        sizer1.Add(self.panel4, 1, wx.EXPAND)
        sizer1.Add(self.panel1, 1, wx.EXPAND)
        self.SetSizer(sizer1)
        sizer1.Fit(self)

        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(sizer1, 1, wx.EXPAND)
        sizer.Add(self.panel2, 1, wx.EXPAND)
        sizer.Add(self.panel3, 1, wx.EXPAND)
        self.SetSizer(sizer)
        #sizer.Fit(self)


        self.log = wx.TextCtrl(self.panel3, style=wx.TE_RICH|wx.TE_MULTILINE)
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(self.log, 1, wx.EXPAND|wx.ALL, 15)
        self.panel3.SetSizer(sizer)

        emptycell = (0,0)
        self.button1 = wx.Button(self.panel4, -1, "Button1", size=wx.Size(150, 70))
        self.button2 = wx.Button(self.panel1, -1, "Button2")
        self.button3 = wx.Button(self.panel1, -1, "Button3")
        self.button4 = wx.Button(self.panel1, -1, "Button4")

        sizer = wx.GridSizer(8,3,0,0)

        sizer.Add(emptycell, 0, wx.EXPAND)
        sizer.Add(self.button1, 0, wx.ALIGN_CENTER|wx.LEFT, 10)
        sizer.Add(emptycell, 0, wx.EXPAND)
        sizer.Add(self.button2, 0, wx.ALIGN_CENTER)
        sizer.Add(self.button3, 0, wx.ALIGN_CENTER)
        sizer.Add(self.button4, 0, wx.ALIGN_CENTER)
        self.panel1.SetSizer(sizer)



        self.figure = Figure()
        self.axes = self.figure.add_subplot(111)
        self.canvas = FigureCanvas(self.panel2, -1, self.figure)

        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(self.canvas, 0, wx.EXPAND)
        self.panel2.SetSizer(sizer)
        #self.panel2.Fit()


        t = arange(0.0, 3.0, 0.01)
        s = sin(2 * pi * t)
        self.axes.plot(t, s)

        #self.Center()


#Every wxWidgets application must have a class derived from wxApp
class MyApp(wx.App):
    # wxWidgets calls this method to initialize the application
    def OnInit(self):

        # Create an instance of our customized Frame class
        self.frame = Frame1(None)
        self.SetTopWindow(self.frame)
        self.frame.Show()
        return True


if __name__ == '__main__':
    application = MyApp(0)
    application.MainLoop()

Desired result

enter image description here

Actual result

enter image description here


Solution

  • I had to hack it about a bit but try to give each panel a sizer of its own and bring them together at the end. Also, use descriptive names, or it soon becomes a morass, which is difficult to follow.

    import wx
    from numpy import arange, sin, pi
    import matplotlib
    matplotlib.use('WXAgg')
    
    from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
    from matplotlib.figure import Figure
    
    
    class Frame1(wx.Frame):
    
        def __init__(self, parent):
    
            wx.Frame.__init__(self, None,
                              pos=wx.Point(0, 0),size=wx.Size(800, 200),
                              style=wx.DEFAULT_FRAME_STYLE | wx.MAXIMIZE )
    
            self.panel1_1 = wx.Panel(self)
            self.panel1_2 = wx.Panel(self)
            self.panel2 = wx.Panel(self)
            self.panel3 = wx.Panel(self)
            self.panel3.SetBackgroundColour('red')
            self.panel1_1.SetBackgroundColour('green')
            self.panel1_2.SetBackgroundColour('blue')
    
    
            self.log = wx.TextCtrl(self.panel3, style=wx.TE_RICH|wx.TE_MULTILINE)
            log_sizer = wx.BoxSizer(wx.HORIZONTAL)
            log_sizer.Add(self.log, 1, wx.EXPAND|wx.ALL, 15)
            self.panel3.SetSizer(log_sizer)
    
            self.button1 = wx.Button(self.panel1_1, -1, "Button1", size=wx.Size(150, 70))
    
            button_sizer1 = wx.GridSizer(1,3,0,0)
            button_sizer1.Add((0,0), 0, wx.ALL, 10)
            button_sizer1.Add(self.button1, 0, wx.ALL, 10)
            button_sizer1.Add((0,0), 0, wx.ALL, 10)
            self.panel1_1.SetSizer(button_sizer1)
    
            self.button2 = wx.Button(self.panel1_2, -1, "Button2")
            self.button3 = wx.Button(self.panel1_2, -1, "Button3")
            self.button4 = wx.Button(self.panel1_2, -1, "Button4")
    
            button_sizer2 = wx.GridSizer(1,3,0,0)
            button_sizer2.Add(self.button2, 0, wx.ALL|wx.ALIGN_LEFT, 10)
            button_sizer2.Add(self.button3, 0, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL, 10)
            button_sizer2.Add(self.button4, 0, wx.ALL|wx.ALIGN_RIGHT, 10)
            self.panel1_2.SetSizer(button_sizer2)
    
            main_button_sizer = wx.BoxSizer(wx.VERTICAL)
            main_button_sizer.Add(self.panel1_1)
            main_button_sizer.Add(self.panel1_2, 1, wx.EXPAND)
    
            self.figure = Figure()
            self.axes = self.figure.add_subplot(111)
            self.canvas = FigureCanvas(self.panel2, -1, self.figure)
    
            fig_sizer = wx.BoxSizer(wx.HORIZONTAL)
            fig_sizer.Add(self.canvas, 0, wx.EXPAND)
            self.panel2.SetSizer(fig_sizer)
    
            main_sizer = wx.BoxSizer(wx.HORIZONTAL)
            main_sizer.Add(main_button_sizer, 1, wx.EXPAND)
            main_sizer.Add(self.panel2, 1, wx.EXPAND)
            main_sizer.Add(self.panel3, 1, wx.EXPAND)
            self.SetSizer(main_sizer)
            self.Layout()
    
            t = arange(0.0, 3.0, 0.01)
            s = sin(2 * pi * t)
            self.axes.plot(t, s)
    
    
    #Every wxWidgets application must have a class derived from wxApp
    class MyApp(wx.App):
        # wxWidgets calls this method to initialize the application
        def OnInit(self):
    
            # Create an instance of our customized Frame class
            self.frame = Frame1(None)
            self.SetTopWindow(self.frame)
            self.frame.Show()
            return True
    
    
    if __name__ == '__main__':
        application = MyApp(0)
        application.MainLoop()
    

    enter image description here