Search code examples
pythongridwxpythonwxwidgetswxgrid

wxPython wx.grid.Grid is not loading fully with scrollbars


Issue

I created an wx application with 1 Frame. The Frame will have menubar, which has open menu option.

When open is clicked, a Wx.grid.Grid must be created in the frame with given rows, columns.

I have been trying hard, but scrollbars are not appearing by default.

I referred to this: https://stackoverflow.com/a/54753248/11658861

Actual Look

Scroll bars are not present which ideally must come automatically.

Post minimize and maximize Look

If I minimize and maximize frame once, then scrollbars are appearing!

Kindly someone please help! I need a solution, which creates proper grid with scrollbars, in same application flow.

Windows V20H2, Python 3.10.7, WxPython 4.2.0

Code (feel free to copy paste this into a Python IDE and test!):

import wx
import wx.grid


class MyForm(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, parent=None, title="A Simple Grid")

        menubar = wx.MenuBar()
        file_menu = wx.Menu()
        menubar.Append(file_menu, "File")
        open_item = wx.MenuItem(file_menu, wx.ID_OPEN, '&Open\tCtrl+O')
        file_menu.Append(open_item)
        self.Bind(wx.EVT_MENU, self.callForm2, open_item)
        self.SetMenuBar(menubar)
        self.Maximize()

    def callForm2(self, event):
        panel = wx.Panel(self)
        myGrid = MyGrid(panel)
        myGrid.fillGrid()

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(myGrid, 1, wx.EXPAND)
        panel.SetSizerAndFit(sizer)


class MyGrid(wx.grid.Grid):
    def __init__(self, parent):
        wx.grid.Grid.__init__(self, parent, style=wx.HSCROLL | wx.VSCROLL)

    def fillGrid(self):
        self.CreateGrid(100, 5)

        self.SetColLabelValue(0, "Column1")
        self.SetColLabelValue(1, "Column2")
        self.SetColLabelValue(2, "Column3")
        self.SetColLabelValue(3, "Column4")
        self.SetColLabelValue(4, "Column5")

        self.SetDefaultColSize(width=350, resizeExistingCols=True)
        self.SetDefaultRowSize(height=30, resizeExistingRows=True)


if __name__ == "__main__":
    app = wx.App(False)
    frame = MyForm().Show()
    app.MainLoop()

Summary

How to properly create a wx.grid.Grid with scrollbars in parent window, when an action is triggered from a child window?

Thanks in advance!


Solution

  • You'll need to use Layout() and Refresh(), at least on Linux, after you have set the sizer.

    Note that the scrollbars will only show if needed, so I've added a 6th column, so the horizontal scrollbar shows too.

    import wx
    import wx.grid
    
    
    class MyForm(wx.Frame):
        def __init__(self):
            wx.Frame.__init__(self, parent=None, title="A Simple Grid")
    
            menubar = wx.MenuBar()
            file_menu = wx.Menu()
            menubar.Append(file_menu, "File")
            open_item = wx.MenuItem(file_menu, wx.ID_OPEN, '&Open\tCtrl+O')
            quit_item = wx.MenuItem(file_menu, wx.ID_EXIT, '&Quit\tCtrl+Q')
            file_menu.Append(open_item)
            file_menu.Append(quit_item)
            self.Bind(wx.EVT_MENU, self.callForm2, open_item)
            self.Bind(wx.EVT_MENU, self.OnExit, id=wx.ID_EXIT)
            self.SetMenuBar(menubar)
            self.Maximize()
    
        def callForm2(self, event):
            panel = wx.Panel(self)
            myGrid = MyGrid(panel)
            myGrid.fillGrid()
    
            sizer = wx.BoxSizer(wx.VERTICAL)
            sizer.Add(myGrid, 1, wx.EXPAND, 0)
            panel.SetSizerAndFit(sizer)
            self.Layout()
            self.Refresh()
    
        def OnExit(self, event):
            self.Destroy()
    
    class MyGrid(wx.grid.Grid):
        def __init__(self, parent):
            wx.grid.Grid.__init__(self, parent, style=wx.HSCROLL | wx.VSCROLL)
    
        def fillGrid(self):
            self.CreateGrid(100, 6)
    
            self.SetColLabelValue(0, "Column1")
            self.SetColLabelValue(1, "Column2")
            self.SetColLabelValue(2, "Column3")
            self.SetColLabelValue(3, "Column4")
            self.SetColLabelValue(4, "Column5")
            self.SetColLabelValue(5, "Column6")
            self.SetDefaultColSize(width=350, resizeExistingCols=True)
            self.SetDefaultRowSize(height=30, resizeExistingRows=True)
    
    if __name__ == "__main__":
        app = wx.App(False)
        frame = MyForm().Show()
        app.MainLoop()