Search code examples
pythonwxpython

Unable to get wxPython Sizers to work correctly


I am a newbie to Python although I have many years' experience in other languages. The main issues I am having is with Sizers. Using only BoxSizers I have managed to get things working as expected. However when I incorporated a GridBagSizer I found that I could only stretch the Window horizontally and not vertically. I have searched through previous queries but not found anything that exactly matches my problem.

I have been bogged down for over a day so thanks in advance for any responses...

The code for the App and Frame is:-

#!/usr/bin/env python
#Boa:App:BoaApp`enter code here`

import wx

import Frame9

modules ={'Frame9': [1, 'Main frame of Application', 'none://Frame9.py']}

class BoaApp(wx.App):
    def OnInit(self):
        self.main = Frame9.create(None)
        self.main.Show()
        self.SetTopWindow(self.main)
        return True

def main():
    application = BoaApp(0)
    application.MainLoop()

if __name__ == '__main__':
    main()




#Boa:Frame:Frame9

import wx

def create(parent):
    return Frame9(parent)

[wxID_FRAME9, wxID_FRAME9BUTTON1, wxID_FRAME9BUTTON2, wxID_FRAME9BUTTON3, 
 wxID_FRAME9PANEL1, wxID_FRAME9STATICTEXT1, wxID_FRAME9STATICTEXT2, 
 wxID_FRAME9STATICTEXT3, wxID_FRAME9STATICTEXT4, wxID_FRAME9STATICTEXT5, 
 wxID_FRAME9STATUSBAR2, wxID_FRAME9TEXTCTRL1, wxID_FRAME9TEXTCTRL2, 
 wxID_FRAME9TEXTCTRL3, wxID_FRAME9TEXTCTRL4, 
] = [wx.NewId() for _init_ctrls in range(15)]

class Frame9(wx.Frame):
    def _init_coll_boxSizer1_Items(self, parent):
        # generated method, don't edit

        parent.AddWindow(self.panel1, 0, border=0, flag=wx.ALIGN_BOTTOM)
        parent.AddWindow(self.statusBar2, 0, border=0, flag=0)
        parent.AddWindow(self.staticText5, 0, border=0, flag=0)

    def _init_sizers(self):
        # generated method, don't edit
        self.boxSizer1 = wx.BoxSizer(orient=wx.VERTICAL)

        self.boxSizer2 = wx.BoxSizer(orient=wx.HORIZONTAL)

        self.gridBagSizer1 = wx.GridBagSizer(hgap=50, vgap=75)

        self.boxSizer3 = wx.BoxSizer(orient=wx.HORIZONTAL)

        self._init_coll_boxSizer1_Items(self.boxSizer1)

        self.SetSizer(self.boxSizer2)

    def _init_ctrls(self, prnt):
        # generated method, don't edit
        wx.Frame.__init__(self, id=wxID_FRAME9, name='', parent=prnt,
              pos=wx.Point(432, 157), size=wx.Size(721, 315),
              style=wx.DEFAULT_FRAME_STYLE, title='Frame9')
        self.SetClientSize(wx.Size(721, 315))
        self.SetMinSize(wx.Size(721, 315))
        self.SetAutoLayout(False)
        self.Bind(wx.EVT_ACTIVATE, self.OnFrame9Activate)

        self.button1 = wx.Button(id=wxID_FRAME9BUTTON1, label='Clear',
              name='button1', parent=self, pos=wx.Point(25, 232),
              size=wx.Size(85, 28), style=0)

        self.button2 = wx.Button(id=wxID_FRAME9BUTTON2, label='Convert',
              name='button2', parent=self, pos=wx.Point(313, 232),
              size=wx.Size(85, 28), style=0)

        self.button3 = wx.Button(id=wxID_FRAME9BUTTON3, label='Now',
              name='button3', parent=self, pos=wx.Point(611, 232),
              size=wx.Size(85, 28), style=0)

        self.staticText1 = wx.StaticText(id=wxID_FRAME9STATICTEXT1,
              label=u'2^10 * Hex', name='staticText1', parent=self,
              pos=wx.Point(0, 0), size=wx.Size(90, 15), style=wx.ALIGN_RIGHT)

        self.staticText2 = wx.StaticText(id=wxID_FRAME9STATICTEXT2,
              label=u'Hex Time', name='staticText2', parent=self,
              pos=wx.Point(0, 0), size=wx.Size(90, 15), style=wx.ALIGN_RIGHT)

        self.textCtrl1 = wx.TextCtrl(id=wxID_FRAME9TEXTCTRL1, name='textCtrl1',
              parent=self, pos=wx.Point(200, 72), size=wx.Size(145, 25),
              style=0, value='textCtrl1')

        self.textCtrl2 = wx.TextCtrl(id=wxID_FRAME9TEXTCTRL2, name='textCtrl2',
              parent=self, pos=wx.Point(520, 72), size=wx.Size(145, 25),
              style=0, value='textCtrl2')

        self.staticText3 = wx.StaticText(id=wxID_FRAME9STATICTEXT3,
              label=u'Epoch Time', name='staticText3', parent=self,
              pos=wx.Point(48, 172), size=wx.Size(90, 15), style=0)

        self.staticText4 = wx.StaticText(id=wxID_FRAME9STATICTEXT4,
              label=u'Date And Time', name='staticText4', parent=self,
              pos=wx.Point(360, 172), size=wx.Size(90, 15), style=0)

        self.textCtrl3 = wx.TextCtrl(id=wxID_FRAME9TEXTCTRL3, name='textCtrl3',
              parent=self, pos=wx.Point(200, 172), size=wx.Size(145, 25),
              style=0, value=u'textCtrl3')

        self.textCtrl4 = wx.TextCtrl(id=wxID_FRAME9TEXTCTRL4, name='textCtrl4',
              parent=self, pos=wx.Point(520, 172), size=wx.Size(145, 25),
              style=0, value=u'textCtrl4')

        self.panel1 = wx.Panel(id=wxID_FRAME9PANEL1, name='panel1', parent=self,
              pos=wx.Point(0, 0), size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
        self.panel1.Show(False)

        self.statusBar2 = wx.StatusBar(id=wxID_FRAME9STATUSBAR2,
              name='statusBar2', parent=self, style=0)
        self.statusBar2.SetStatusText(u'Current status...')
        self.statusBar2.SetToolTipString(u'statusBar2')

        self.staticText5 = wx.StaticText(id=wxID_FRAME9STATICTEXT5, label=u'',
              name='staticText5', parent=self, pos=wx.Point(0, 20),
              size=wx.Size(1, 15), style=0)

        self._init_sizers()

    def __init__(self, parent):
        self._init_ctrls(parent)

    def OnSize(self, event):
             event.Skip()
             cl_size = self.GetClientSize()
             if cl_size.height < self.min_ClientHeight:
                  self.SetClientSize((cl_size.width, self.min_ClientHeight)) 

    def OnFrame9Activate(self, event):

        #self.panel = wx.Panel(self)

        self._init_sizers()

        self.gridBagSizer1.Add(self.staticText1, pos=(1,1), span = (1,1), flag=wx.EXPAND)
        self.gridBagSizer1.Add(self.textCtrl1, pos=(1,2), span = (1,2), flag=wx.EXPAND)
        self.gridBagSizer1.Add(self.staticText2, pos=(1,5), span = (1,1), flag=wx.EXPAND)
        self.gridBagSizer1.Add(self.textCtrl2, pos=(1,6), span = (1,2), flag=wx.EXPAND)

        #Add second row
        self.gridBagSizer1.Add(self.staticText3, pos=(2,1), span = (1,1), flag=wx.EXPAND)
        self.gridBagSizer1.Add(self.textCtrl3, pos=(2,2), span = (1,2), flag=wx.EXPAND)
        self.gridBagSizer1.Add(self.staticText4, pos=(2,5), span = (1,1), flag=wx.EXPAND)
        self.gridBagSizer1.Add(self.textCtrl4, pos=(2,6), span = (1,2), flag=wx.EXPAND)
        self.gridBagSizer1.Add(self.staticText5, pos=(2,8), span = (1,1), flag=wx.EXPAND)

        self.gridBagSizer1.AddGrowableCol(0)
        self.gridBagSizer1.AddGrowableCol(1)
        self.gridBagSizer1.AddGrowableCol(2)
        self.gridBagSizer1.AddGrowableCol(4)
        self.gridBagSizer1.AddGrowableCol(5)
        self.gridBagSizer1.AddGrowableCol(6)
        self.gridBagSizer1.AddGrowableCol(7)
        self.gridBagSizer1.AddGrowableCol(8)
        self.gridBagSizer1.AddGrowableRow(0)
        self.gridBagSizer1.AddGrowableRow(1)
        self.gridBagSizer1.AddGrowableRow(2)
        self.gridBagSizer1.AddGrowableRow(3)

        self.boxSizer1.Add(self.gridBagSizer1, 0, wx.ALL|wx.EXPAND)

        self.boxSizer3.Add((20, 20), 1)
        self.boxSizer3.Add(self.button1)
        self.boxSizer3.Add((20, 20), 1)
        self.boxSizer3.Add(self.button2)
        self.boxSizer3.Add((20, 20), 1)
        self.boxSizer3.Add(self.button3)
        self.boxSizer3.Add((20, 20), 1)

        self.boxSizer1.Add(self.boxSizer3, 0, wx.ALL|wx.EXPAND|wx.BOTTOM, 50)

        self.SetSizer(self.boxSizer1) # new code
        self.boxSizer1.Fit(self)

        event.Skip()

Solution

  • Change this:

    self.boxSizer1.Add(self.gridBagSizer1, 0, wx.ALL|wx.EXPAND)
    

    to:

    self.boxSizer1.Add(self.gridBagSizer1, 1, wx.ALL|wx.EXPAND)
    

    Following is an alternative way of doing your layout with wxPython using sized_controls. I really like them as I now adays find it easier to layout screens with them instead of using a UI designer like Boa (which I liked a lot and have used in the past).

    A few notes to the code, I used wxversion as I have a few wxPython versions installed on my machine, so needed to select one.

    To find out more about: sized controls - http://wiki.wxpython.org/SizedControls WIT - http://wiki.wxpython.org/Widget%20Inspection%20Tool

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-#
    
    import wxversion
    wxversion.select('2.9.5')
    
    import wx
    import wx.lib.sized_controls as SC
    
    class AltFrame(SC.SizedFrame):
    
        def __init__(self, *args, **kwds):
            super(AltFrame, self).__init__(*args, **kwds)
    
            paneCont = self.GetContentsPane()
    
            paneControls = SC.SizedPanel(paneCont)
            paneControls.SetSizerType('grid', options={'cols': 2,})
            paneControls.SetSizerProps(expand=True, proportion=1)
            paneButtons = SC.SizedPanel(paneCont)
            paneButtons.SetSizerType('grid', options={'cols': 3,})
            paneButtons.SetSizerProps(align='center')
    
            self.button1 = wx.Button(paneButtons, label='Clear',
                  name='button1')
    
            self.button2 = wx.Button(paneButtons, label='Convert',
                  name='button2')
    
            self.button3 = wx.Button(paneButtons, label='Now',
                  name='button3')
    
            self.staticText1 = wx.StaticText(paneControls, label=u'2^10 * Hex',
                                             name='staticText1',
                                             style=wx.ALIGN_RIGHT)
            self.textCtrl1 = wx.TextCtrl(paneControls, name='textCtrl1',
                                         value='textCtrl1')
    
            self.staticText2 = wx.StaticText(paneControls, label=u'Hex Time',
                                             name='staticText2',
                                             style=wx.ALIGN_RIGHT)
            self.textCtrl2 = wx.TextCtrl(paneControls, name='textCtrl2',
                                         value='textCtrl2')
    
            self.staticText3 = wx.StaticText(paneControls,
                  label=u'Epoch Time', name='staticText3')
            self.textCtrl3 = wx.TextCtrl(paneControls, name='textCtrl3')
    
            self.staticText4 = wx.StaticText(paneControls,
                  label=u'Date And Time', name='staticText4')
            self.textCtrl4 = wx.TextCtrl(paneControls, name='textCtrl4')
    
            self.statusBar2 = wx.StatusBar(self, name='statusBar2')
            self.statusBar2.SetStatusText(u'Current status...')
            self.statusBar2.SetToolTipString(u'statusBar2')
    
            self.SetStatusBar(self.statusBar2)
    
    if __name__ == "__main__":
        import wx.lib.mixins.inspection as WIT
    
        app = WIT.InspectableApp()
        frame = AltFrame(None)
        frame.Show()
        app.MainLoop()