wxpython: adding rows to wxgrid dynamically does not fit to panel
Question: I have a wxgrid inside a resizable scrollable panel. I dynamically
add/hide/show rows in wxgrid. When I try to add/show more rows in wxgrid, it
does not fit to the available space in panel but instead occupies a small area
it had been occupying previously with a scrollbar for wxgrid.

Like this:

![enter image description here](http://i.stack.imgur.com/7T4DV.jpg)

But after I resize the panel or frame, then it fits perfectly. Like this:

![enter image description here](http://i.stack.imgur.com/vd2xs.jpg)

How can I make it to fit properly without needing to resize the panel?

I have tried all combinations of wx.EXPAND, wx.GROW, wx.ALL while adding grid
to sizer and also tried gridobj.Layout() Nothing works. Any Ideas?

Iam using wx 3.0 with python 2.7 on windows 7

Edit: Here's my code

controls.py

    
    
    import wx
    import wx.grid
    import wx.combo
    class SimpleGrid(wx.grid.Grid):
        def __init__(self, parent):
            wx.grid.Grid.__init__(self, parent, -1)
            self.CreateGrid(10, 5)
            for i in range(10):
                self.SetRowLabelValue(i,str(i))
    
    class ListCtrlComboPopup(wx.ListCtrl, wx.combo.ComboPopup):
    
        def __init__(self,parent):
            self.gfobj = parent
            self.PostCreate(wx.PreListCtrl())
            self.parent = parent
            wx.combo.ComboPopup.__init__(self)
    
        def AddItem(self, txt):
            self.InsertStringItem(self.GetItemCount(), txt)
            self.Select(0)
    
        def GetSelectedItems(self):
          del self.gfobj.selection[:]
          current = -1
          while True:
                next = self.GetNextSelected(current)
                if next == -1:
                    return
                self.gfobj.selection.append(next)
                current = next
    
        def onItemSelected(self, event):
            item = event.GetItem()
            self.GetSelectedItems()
            self.parent.draw_plot()
    
        def onItemDeSelected(self, event):
            self.GetSelectedItems()
            self.parent.draw_plot()
    
    
        def Init(self):
            """ This is called immediately after construction finishes.  You can
            use self.GetCombo if needed to get to the ComboCtrl instance. """
            self.value = -1
            self.curitem = -1
    
    
        def Create(self, parent):
            """ Create the popup child control. Return True for success. """
            wx.ListCtrl.Create(self, parent,
                               style=wx.LC_LIST|wx.SIMPLE_BORDER)
            self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.onItemSelected)
            self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.onItemDeSelected)
            return True
    
    
        def GetControl(self):
            """ Return the widget that is to be used for the popup. """
            return self
    
        def SetStringValue(self, val):
            """ Called just prior to displaying the popup, you can use it to
            'select' the current item. """
            idx = self.FindItem(-1, val)
            if idx != wx.NOT_FOUND:
                self.Select(idx)
    
    
        def GetStringValue(self):
            """ Return a string representation of the current item. """
            a = self.GetItemText(self.value)
            if self.value >= 0:
                return a
            return ""
    
        def OnPopup(self):
            """ Called immediately after the popup is shown. """
            self.state = []
            for i in range(self.GetItemCount()):
                item = self.GetItem(itemId=i)
                self.state.append(item.GetState())
                #print self.state
            wx.combo.ComboPopup.OnPopup(self)
    
        def OnDismiss(self):
            " Called when popup is dismissed. """
            wx.combo.ComboPopup.OnDismiss(self)
    

main.py

    
    
    import wx
    import wx.lib.scrolledpanel
    from controls import SimpleGrid
    from controls import ListCtrlComboPopup
    
    
    class GraphFrame(wx.Frame):
        title = 'Demo: Data Trending Tool'
    
        def __init__(self):
            self.selection = []
            self.displaySize = wx.DisplaySize() 
            wx.Frame.__init__(self, None, -1, self.title,
                     style = wx.DEFAULT_FRAME_STYLE,
                     size = (self.displaySize[0]/2, self.displaySize[1]/2))        
            self.containingpanel = wx.Panel(self, -1)
            self.toppanel = wx.Panel(self, -1)
            self.splittedwin = wx.SplitterWindow(self.containingpanel, wx.ID_ANY, style=wx.SP_3D | wx.SP_BORDER)
            self.splittedwin.SetMinimumPaneSize(20)
            self.gridpanel = wx.lib.scrolledpanel.ScrolledPanel(self.splittedwin,-1, style = wx.SUNKEN_BORDER)        
            self.panel = wx.lib.scrolledpanel.ScrolledPanel(self.splittedwin,-1, style = wx.SUNKEN_BORDER)
    
            #### GRID
            self.grid = SimpleGrid(self.gridpanel)
            self.gridpanelsizer= wx.BoxSizer(wx.HORIZONTAL)
            self.gridpanelsizer.Add(self.grid, wx.GROW)
            self.gridpanel.SetSizer(self.gridpanelsizer)
            self.gridpanelsizer.Fit(self)             
            #### COMBOBOX
            self.cc = wx.combo.ComboCtrl(self.toppanel, style=wx.CB_READONLY, size=(200,-1), )
            self.cc.SetPopupMaxHeight(140)
            popup = ListCtrlComboPopup(self)
            self.cc.SetPopupControl(popup)
            self.cc.SetText("--select--")
            # Add some items to the listctrl
            for i in range(10):
                popup.AddItem(str(i))
    
            #### SIZER FOR COMBOBOX 
            self.cbpanelsizer= wx.BoxSizer(wx.HORIZONTAL)
            self.cbpanelsizer.Add(self.cc, border = 5,flag = wx.LEFT)
            self.toppanel.SetSizer(self.cbpanelsizer)
    
    
            self.splittedwin.SplitHorizontally(self.gridpanel,self.panel,100)
    
            ##### SIZER FOR CONTAININGPANEL
            self.cpsizer = wx.BoxSizer(wx.VERTICAL) 
            self.cpsizer.Add(self.splittedwin, 1, wx.EXPAND, 0)
            self.containingpanel.SetSizer(self.cpsizer)
            self.cpsizer.Fit(self.containingpanel)
    
            mainsizer = wx.BoxSizer(wx.VERTICAL)
            mainsizer.Add(self.toppanel, 0, wx.EXPAND)
            mainsizer.Add(self.containingpanel, 1, wx.EXPAND)
            self.SetSizerAndFit(mainsizer)
    
            self.panel.SetAutoLayout(1)
            self.panel.SetupScrolling()
            self.gridpanel.SetAutoLayout(1)
            self.gridpanel.SetupScrolling()
            self.draw_plot()
    
        def draw_plot(self):
            for i in range(10):  
              if i in self.selection:
                 self.grid.ShowRow(i)
              else:
                 self.grid.HideRow(i) 
            self.Layout()
            #self.gridpanel.Layout()
    
    if __name__ == "__main__":
    
      app = wx.PySimpleApp()
      app.frame = GraphFrame()
      app.frame.Show()
    
      app.MainLoop()
    

To simulate: 1\. run main.py It displays a splitted window with a grid with
single row in one panel.

  2. Use the drop down to select more than one item (hold ctrl and select)
  3. The wxgrid is cramped to one row space with a wxgrid scrollbar
  4. Resize the panel using the splitter or resize the window. Now all the selected rows appear as required.


Answer: A great tool to debug this is the WIT
(<http://wiki.wxpython.org/Widget%20Inspection%20Tool>)

With your corrected code I can get it to grow by forcing the sash position,
not ideal, but it shows that the 'problem' is with the splitter.

    
    
    import wx
    import wx.lib.scrolledpanel
    from controls import SimpleGrid
    from controls import ListCtrlComboPopup
    
    
    class GraphFrame(wx.Frame):
        title = 'Demo: Data Trending Tool'
    
        def __init__(self):
            self.selection = []
            self.displaySize = wx.DisplaySize() 
            wx.Frame.__init__(self, None, -1, self.title,
                              style = wx.DEFAULT_FRAME_STYLE,
                              size = (self.displaySize[0]/2, self.displaySize[1]/2))        
            self.containingpanel = wx.Panel(self, -1)
            self.toppanel = wx.Panel(self, -1)
            self.splittedwin = wx.SplitterWindow(self.containingpanel, wx.ID_ANY, style=wx.SP_3D | wx.SP_BORDER)
            self.splittedwin.SetMinimumPaneSize(20)
            self.gridpanel = wx.lib.scrolledpanel.ScrolledPanel(self.splittedwin,-1, style = wx.SUNKEN_BORDER)        
            self.panel = wx.lib.scrolledpanel.ScrolledPanel(self.splittedwin,-1, style = wx.SUNKEN_BORDER)
    
            #### GRID
            self.grid = SimpleGrid(self.gridpanel)
            self.gridpanelsizer= wx.BoxSizer(wx.HORIZONTAL)
            self.gridpanelsizer.Add(self.grid, wx.GROW)
            self.gridpanel.SetSizer(self.gridpanelsizer)
            self.gridpanelsizer.Fit(self)             
            #### COMBOBOX
            self.cc = wx.combo.ComboCtrl(self.toppanel, style=wx.CB_READONLY, size=(200,-1), )
            self.cc.SetPopupMaxHeight(140)
            popup = ListCtrlComboPopup(self)
            self.cc.SetPopupControl(popup)
            self.cc.SetText("--select--")
            # Add some items to the listctrl
            for i in range(10):
                popup.AddItem(str(i))
    
            #### SIZER FOR COMBOBOX 
            self.cbpanelsizer= wx.BoxSizer(wx.HORIZONTAL)
            self.cbpanelsizer.Add(self.cc, border = 5,flag = wx.LEFT)
            self.toppanel.SetSizer(self.cbpanelsizer)
    
    
            self.splittedwin.SplitHorizontally(self.gridpanel, self.panel, 50)
    
            ##### SIZER FOR CONTAININGPANEL
            self.cpsizer = wx.BoxSizer(wx.VERTICAL) 
            self.cpsizer.Add(self.splittedwin, 1, wx.EXPAND, 0)
            self.containingpanel.SetSizer(self.cpsizer)
    
            mainsizer = wx.BoxSizer(wx.VERTICAL)
            mainsizer.Add(self.toppanel, 0, wx.EXPAND)
            mainsizer.Add(self.containingpanel, 1, wx.EXPAND)
            self.SetSizer(mainsizer)
    
            self.panel.SetupScrolling()
            self.gridpanel.SetupScrolling()
            self.draw_plot()
    
        def draw_plot(self):
            for i in range(10):  
                if i in self.selection:
                    self.grid.ShowRow(i)
                else:
                    self.grid.HideRow(i)
    
            s = self.grid.GetBestSize()
            print(s)
            self.splittedwin.SetSashPosition(s[1])
    
    
    if __name__ == "__main__":
    
        from wx.lib.mixins.inspection import InspectableApp
        app = InspectableApp()
        app.frame = GraphFrame()
        app.frame.Show()
    
        app.MainLoop()
    

