Search code examples
scrollwindowwxpythongridbagsizer

wxpython GridBagSizer inside ScrolledWindow not working


Good evening/morning,

I have been working on a program and have realized that on lower resolutions, most of the program gets cut off. To counteract this, I decided to add a scrolledwindow to the GUI. Looking around, I found this example:

import wx as wx

class MainFrame(wx.Frame):
    def __init__(self, *args, **kwargs):
        wx.Frame.__init__(self, *args, **kwargs)

        #Panel that holds all the other panels
        self.mainPanel = wx.ScrolledWindow(self, -1)
        self.mainPanel.SetScrollbars(1, 1, 1, 1)
        self.mainPanel.SetBackgroundColour("LIGHT GREY")

        #Panels in mainPanel
        self.lefttopPanel = wx.Panel(self.mainPanel, -1)
        self.lefttopPanel.SetBackgroundColour("WHITE")        
        self.sizewidgets(self.panelwidgets(
                         text='Left Top Panel', 
                         num=12,
                         parent=self.lefttopPanel),
                         parent=self.lefttopPanel)        

        self.leftmiddlePanel = wx.Panel(self.mainPanel, -1)
        self.leftmiddlePanel.SetBackgroundColour("WHITE")        
        self.sizewidgets(self.panelwidgets(
                         text='Left Middle Panel',
                         num=6,
                         parent=self.leftmiddlePanel),
                         parent=self.leftmiddlePanel)

        self.leftbottomPanel = wx.Panel(self.mainPanel, -1)
        self.leftbottomPanel.SetBackgroundColour("WHITE")
        self.sizewidgets(self.panelwidgets(
                         text='Left Bottom Panel',
                         num=8,
                         parent=self.leftbottomPanel),
                         parent=self.leftbottomPanel)

        self.righttopPanel = wx.Panel(self.mainPanel, -1)
        self.righttopPanel.SetBackgroundColour("WHITE")        
        self.sizewidgets(self.panelwidgets(
                         text='Right Top Panel',
                         num=8,
                         parent=self.righttopPanel),
                         parent=self.righttopPanel)

        self.rightbottomPanel = wx.Panel(self.mainPanel, -1)
        self.rightbottomPanel.SetBackgroundColour("WHITE")
        self.sizewidgets(self.panelwidgets(
                         text='Right Bottom Panel',
                         num=8,
                         parent=self.rightbottomPanel),
                         parent=self.rightbottomPanel)


        mpsizer = wx.GridBagSizer(vgap=4, hgap=4)
        mpsizer.Add(self.lefttopPanel, pos=(0,0), span=(1,1), flag=wx.EXPAND)
        mpsizer.Add(self.leftmiddlePanel, pos=(1,0), span=(1,1), flag=wx.EXPAND)
        mpsizer.Add(self.leftbottomPanel, pos=(2,0), span=(1,2), flag=wx.EXPAND)
        mpsizer.Add(self.righttopPanel, pos=(0,1), span=(2,2), flag=wx.EXPAND)
        mpsizer.Add(self.rightbottomPanel, pos=(2,2), span=(1,1), flag=wx.EXPAND)
        mpsizer.AddGrowableCol(1)
        mpsizer.AddGrowableRow(1)
        self.mainPanel.SetSizer(mpsizer)

        #Adding a refresh to resize event
        self.Bind(wx.EVT_SIZE, self.OnResize)

        self.Show()

    def OnResize(self, event):
        self.Refresh()
        event.Skip()

    def sizewidgets(self, widgetlist , parent):
        psizer = wx.GridSizer(cols=2, vgap=5,hgap=5)
        for widget in widgetlist:
            psizer.Add(widget)
        parent.SetSizer(psizer)



    def panelwidgets(self, text, num, parent):
        widgets = []
        for i in range(num):
            widgets += [wx.StaticText(parent, label=text)]
        return widgets

if __name__ == "__main__":
    app = wx.App()
    MainFrame(None, size=(800, 800), title="GridBagSizer Problem")
    app.MainLoop()

That example worked great, so I decided to try to modify it to work with my program, since I have not had luck in just adding a scrolledwindow to my whole program, so I made these changes:

import wx as wx

class MainFrame(wx.Frame):
    def __init__(self, *args, **kwargs):
        wx.Frame.__init__(self, *args, **kwargs)

        #Panel that holds all the other panels
        self.mainPanel = wx.ScrolledWindow(self, -1)
        self.mainPanel.SetScrollbars(1, 1, 1, 1)
        self.mainPanel.SetBackgroundColour("LIGHT GREY")

    # Handles the c reation of all of the static text labels
    def make_label(text, starty, startx, height, width):
        self.label = wx.StaticText(self, -1, text, wx.DefaultPosition, wx.DefaultSize)
        sizer.Add(self.label, (starty, startx), (height, width), wx.EXPAND)
        return self.label

        sizer = wx.GridBagSizer()
    for i in range(0, 4):   
        # all the labels
        make_label('Voltage', 7, i*5, 1, 1)
        make_label('Current', 8, i*5, 1, 1)
        make_label('Power', 9, i*5, 1, 1)
        make_label('Rail 1', 6, (i*5)+1, 1, 1)
        make_label('Rail 2', 6, (i*5)+2, 1, 1)
        make_label('Rail 3', 6, (i*5)+3, 1, 1)  
        make_label('Total Power', 6, (i*5)+4, 1, 1)
        make_label('Status:', 14, (i*5), 1, 1)

    sizer.AddGrowableRow(1)
    sizer.AddGrowableCol(1)
        self.mainPanel.SetSizer(sizer)

        #Adding a refresh to resize event
        self.Bind(wx.EVT_SIZE, self.OnResize)

        self.Show()

    def OnResize(self, event):
        self.Refresh()
        event.Skip()

    def sizewidgets(self, widgetlist , parent):
        psizer = wx.GridSizer(cols=2, vgap=5,hgap=5)
        for widget in widgetlist:
            psizer.Add(widget)
        parent.SetSizer(psizer)



    def panelwidgets(self, text, num, parent):
        widgets = []
        for i in range(num):
            widgets += [wx.StaticText(parent, label=text)]
        return widgets

if __name__ == "__main__":
    app = wx.App()
    MainFrame(None, size=(800, 800), title="GridBagSizer Problem")
    app.MainLoop()

For some reason, with the changes I make however, the scrollbar just sits in the top left corner and is not functional. The same thing happens when I try to add it to my larger program as well. Can anyone help me out with why this is happening?


Solution

  • The child widgets that are created by

    self.label = wx.StaticText(self, -1, text, wx.DefaultPosition, wx.DefaultSize)
    

    have self as the parent, which is the MainFrame class.

    Change it so that the parent is the instance of scrolled window as follows

    self.label = wx.StaticText(self.mainPanel, -1, text, wx.DefaultPosition, wx.DefaultSize)