Search code examples
pythonwxpython

How to understand wxGridBagSizer?


I was trying to design gui for my app using wxPython. I was using wx.GridBagSizer, but I encountered a few problems with it.

enter image description here

First layout is what I get from my code and the second one is the layout I would like to get. I think I don't understand pos and span attributes correctly. I would be grateful for any explanation. Below is my current code:

class MyFrame1 ( wx.Frame ):

def __init__( self, parent ):
    wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 561,401 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )

    self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )

    gbSizer1 = wx.GridBagSizer( 0, 0 )
    gbSizer1.SetFlexibleDirection( wx.BOTH )
    gbSizer1.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED )

    gbSizer1.SetMinSize( wx.Size( 0,0 ) ) 
    self.m_panel25 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.Size( 10,10 ), wx.TAB_TRAVERSAL )
    self.m_panel25.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_WINDOWTEXT ) )

    gbSizer1.Add( self.m_panel25, wx.GBPosition( 0, 0 ), wx.GBSpan( 1, 3 ), wx.EXPAND |wx.ALL, 5 )

    self.m_panel41 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
    gbSizer1.Add( self.m_panel41, wx.GBPosition( 5, 0 ), wx.GBSpan( 1, 1 ), wx.EXPAND |wx.ALL, 5 )

    self.m_panel26 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.Size( 10,10 ), wx.TAB_TRAVERSAL )
    self.m_panel26.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_INFOBK ) )

    gbSizer1.Add( self.m_panel26, wx.GBPosition( 0, 3 ), wx.GBSpan( 1, 1 ), wx.ALL, 5 )

    self.m_panel28 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.Size( 10,10 ), wx.TAB_TRAVERSAL )
    self.m_panel28.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_INFOBK ) )

    gbSizer1.Add( self.m_panel28, wx.GBPosition( 0, 4 ), wx.GBSpan( 1, 1 ), wx.ALL, 5 )

    self.m_panel27 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.Size( 10,10 ), wx.TAB_TRAVERSAL )
    self.m_panel27.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_INFOBK ) )

    gbSizer1.Add( self.m_panel27, wx.GBPosition( 0, 5 ), wx.GBSpan( 1, 1 ), wx.ALL, 5 )

    self.m_panel29 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.Size( 10,10 ), wx.TAB_TRAVERSAL )
    self.m_panel29.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_INFOBK ) )

    gbSizer1.Add( self.m_panel29, wx.GBPosition( 0, 6 ), wx.GBSpan( 1, 3 ), wx.EXPAND |wx.ALL, 5 )

    self.m_panel30 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.Size( 10,10 ), wx.TAB_TRAVERSAL )
    self.m_panel30.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_INFOTEXT ) )

    gbSizer1.Add( self.m_panel30, wx.GBPosition( 1, 3 ), wx.GBSpan( 5, 6 ), wx.EXPAND |wx.ALL, 5 )

    self.m_panel31 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.Size( 10,10 ), wx.TAB_TRAVERSAL )
    self.m_panel31.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_HIGHLIGHT ) )

    gbSizer1.Add( self.m_panel31, wx.GBPosition( 1, 0 ), wx.GBSpan( 1, 3 ), wx.ALL, 5 )

    self.m_panel32 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.Size( 10,10 ), wx.TAB_TRAVERSAL )
    self.m_panel32.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_HIGHLIGHT ) )

    gbSizer1.Add( self.m_panel32, wx.GBPosition( 2, 0 ), wx.GBSpan( 1, 3 ), wx.ALL, 5 )

    self.m_panel39 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.Size( 10,10 ), wx.TAB_TRAVERSAL )
    self.m_panel39.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_HIGHLIGHT ) )

    gbSizer1.Add( self.m_panel39, wx.GBPosition( 3, 0 ), wx.GBSpan( 1, 3 ), wx.ALL, 5 )

    self.m_panel40 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.Size( 10,10 ), wx.TAB_TRAVERSAL )
    self.m_panel40.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_HIGHLIGHT ) )

    gbSizer1.Add( self.m_panel40, wx.GBPosition( 4, 0 ), wx.GBSpan( 1, 3 ), wx.ALL, 5 )


    self.SetSizer( gbSizer1 )
    self.Layout()

    self.Centre( wx.BOTH )

Solution

  • I think you are really close. Take note of the changes made. What about this:

    import wx
    
    class MyFrame1 ( wx.Frame ):
    
        def __init__( self, parent ):
            wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 561,401 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
    
            self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
    
            gbSizer1 = wx.GridBagSizer( 0, 0 )
            gbSizer1.SetFlexibleDirection( wx.BOTH )
            gbSizer1.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED )
    
            gbSizer1.SetMinSize( wx.Size( 0,0 ) )
            self.m_panel25 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.Size( 40,10 ), wx.TAB_TRAVERSAL )
            self.m_panel25.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_WINDOWTEXT ) )
    
            gbSizer1.Add( self.m_panel25, wx.GBPosition( 0, 0 ), wx.GBSpan( 1, 3 ), wx.EXPAND |wx.ALL, 5 )
    
            self.m_panel41 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
            gbSizer1.Add( self.m_panel41, wx.GBPosition( 5, 0 ), wx.GBSpan( 1, 1 ), wx.EXPAND |wx.ALL, 5 )
    
            self.m_panel26 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.Size( 10,10 ), wx.TAB_TRAVERSAL )
            self.m_panel26.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_INFOBK ) )
    
            gbSizer1.Add( self.m_panel26, wx.GBPosition( 0, 3 ), wx.GBSpan( 1, 1 ), wx.ALL, 5 )
    
            self.m_panel28 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.Size( 10,10 ), wx.TAB_TRAVERSAL )
            self.m_panel28.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_INFOBK ) )
    
            gbSizer1.Add( self.m_panel28, wx.GBPosition( 0, 4 ), wx.GBSpan( 1, 1 ), wx.ALL, 5 )
    
            self.m_panel27 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.Size( 10,10 ), wx.TAB_TRAVERSAL )
            self.m_panel27.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_INFOBK ) )
    
            gbSizer1.Add( self.m_panel27, wx.GBPosition( 0, 5 ), wx.GBSpan( 1, 1 ), wx.ALL, 5 )
    
            self.m_panel29 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.Size( 40,10 ), wx.TAB_TRAVERSAL )
            self.m_panel29.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_INFOBK ) )
    
            gbSizer1.Add( self.m_panel29, wx.GBPosition( 0, 6 ), wx.GBSpan( 1, 3 ), wx.EXPAND |wx.ALL, 5 )
    
            self.m_panel40 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.Size( 40,10 ), wx.TAB_TRAVERSAL )
            self.m_panel40.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_INFOTEXT ) )
    
            gbSizer1.Add( self.m_panel40, wx.GBPosition( 1, 3 ), wx.GBSpan( 5, 6 ), wx.EXPAND |wx.ALL, 5 )
    
            self.m_panel31 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.Size( 40,10 ), wx.TAB_TRAVERSAL )
            self.m_panel31.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_HIGHLIGHT ) )
    
            gbSizer1.Add( self.m_panel31, wx.GBPosition( 1, 0 ), wx.GBSpan( 1, 3 ), wx.ALL, 5 )
    
            self.m_panel32 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.Size( 40,10 ), wx.TAB_TRAVERSAL )
            self.m_panel32.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_HIGHLIGHT ) )
    
            gbSizer1.Add( self.m_panel32, wx.GBPosition( 2, 0 ), wx.GBSpan( 1, 3 ), wx.ALL, 5 )
    
            self.m_panel39 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.Size( 40,10 ), wx.TAB_TRAVERSAL )
            self.m_panel39.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_HIGHLIGHT ) )
    
            gbSizer1.Add( self.m_panel39, wx.GBPosition( 3, 0 ), wx.GBSpan( 1, 3 ), wx.ALL, 5 )
    
            self.m_panel40 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.Size( 40,10 ), wx.TAB_TRAVERSAL )
            self.m_panel40.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_HIGHLIGHT ) )
    
            gbSizer1.Add( self.m_panel40, wx.GBPosition( 4, 0 ), wx.GBSpan( 1, 3 ), wx.ALL, 5 )
    
    
            self.SetSizer( gbSizer1 )
            self.Layout()
    
            self.Centre( wx.BOTH )
    
    
    def main():
        app = wx.App(False)
        MainFrame = MyFrame1(None)
        MainFrame.Show()
        app.MainLoop()
    
    if __name__ == '__main__':
        main()
    

    When the above code is run it outputs:

    enter image description here

    Edit

    First. I haven't used the GridBagSizer before, so I apologize if the information that I give is misleading in any way. But wx.Size in this instance is part of a wx.Panel class, where as wx.GBSpan is part of a wx.GridBagSizer class. As such you might be able to expand the panel to fit the span, but I am not sure how to do this at the moment.

    It would appear that wx.GBSpan() defaults to 1 row cell and 1 column cell.

    So, wx.GBSpan(rowspan=1,colspan=1) is the same as wx.GBSpan(1, 1).

    And if you take a look at Robin Dunn's answer from the mailing lists archive...

    http://wxpython-users.1045709.n5.nabble.com/Problem-with-GridBagSizer-and-span-td2359250.html

    > Hi all 
    > 
    > I understand what the 'span' argument to wx.GridBagSizer.Add() means, but it 
    > is not behaving as I would expect. 
    > 
    > Assume I have two columns in my GBS, one with a width of 20 and one with a 
    > width of 30. 
    > 
    > If I add a row containing an element with a width of 40, spanning both 
    > columns, I expected that the existing sizes and positions would not change, 
    > as there is ample room to fit the new row into the available width. 
    > 
    > In practice, the overall width is increased, and ugly spaces start to 
    > appear.
    ... [show rest of quote]
    
    IIRC when an item spans columns then its width is divided evenly across 
    all the columns.  In other words, for an item that is 100 pixels wide 
    that is spanned across 5 columns, then each column takes 'ownership' of 
    20 pixels for that item.  So even if everything else in that column is 
    only 10 pixels wide, the sizer is still going to assume that the col 
    needs 20 pixels because of that column's share of the spanning item. 
    

    So for example with your Code:

    self.m_panel29 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.Size( 10,10 ), wx.TAB_TRAVERSAL )
    self.m_panel29.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_INFOBK ) )
    gbSizer1.Add( self.m_panel29, wx.GBPosition( 0, 6 ), wx.GBSpan( 1, 3 ), wx.EXPAND |wx.ALL, 5 )
    

    wx.GBSpan(rowspan=1, colspan=3) and wx.Size( 10, 10 ) width = 10 and height = 10.

    Also worth taking a look at in regards to Size and expanding panels: