Search code examples
pythonwxpythonscrollbargnuradio

Add a vertical scrollbar to a wxFrame accross multiple wxPanels


I want a vertical scrollbar throughout the frame (Top Block). I am able to get vertical scrollbars for the individual panels -

Top Block

Here both the plots are threads plotted by the same class.

Here is the code which sets up the top block in gnuradio -

class top_block_gui(gr.top_block):
    def __init__(self, title='', size=default_gui_size):
        gr.top_block.__init__(self)
        .............
        self._frame = wx.Frame(None, title=title)
        self._panel = panel.Panel(self._frame)
        .............
    def Run(self, start=True, max_nouts=0):
        #setup app
        self._frame.Bind(wx.EVT_CLOSE, _quit)
        self._sizer = wx.BoxSizer(wx.VERTICAL)
        self._sizer.Add(self._panel, 0, wx.EXPAND)
        self._frame.SetSizerAndFit(self._sizer)
        self._frame.SetAutoLayout(True)
        self._frame.Show(True)
        self._app.SetTopWindow(self._frame)
        #start flow graph
        ..................

Edit 1 - As suggested in Method 1 by pss -

class top_block_gui(gr.top_block):
    def __init__(self, title='', size=default_gui_size):
        gr.top_block.__init__(self)
        .............
        self._frame = wx.Frame(None, title=title)
        self._scroll = wx.ScrolledWindow(self._frame,-1) #Added
        self._scroll.SetScrollbars(1,1,600,400) #Added
        self._panel = panel.Panel(self._scroll) #Changed
        .............
    def Run(self, start=True, max_nouts=0):
        #setup app
        self._frame.Bind(wx.EVT_CLOSE, _quit)
        self._sizer = wx.BoxSizer(wx.VERTICAL)
        self._sizer.Add(self._panel, 0, wx.EXPAND)
        self._scroll.SetSizerAndFit(self._sizer) #Changed
        self._frame.SetAutoLayout(True)
        self._frame.Show(True)
        self._app.SetTopWindow(self._frame)
        #start flow graph
        ..................

But I still get the same results as before. No scrollbar appears. Do I have to set its visibility true somewhere by any chance?


Solution

  • You can use either of the following ways to do so:

    Method 1: You can use wx.ScrolledWindow

    Example code:

    import wx
    import wx.lib.scrolledpanel
    
    class GUI(wx.Frame):
        def __init__(self):
            wx.Frame.__init__(self, None, wx.ID_ANY, "Test app v1.0", style = wx.DEFAULT_FRAME_STYLE )
            self.Center()
            self.CreateStatusBar()
            mainSizer = wx.BoxSizer(wx.VERTICAL)
            self.scroll = wx.ScrolledWindow(self, -1)
            self.scroll.SetScrollbars(1, 1, 600, 400)
            panelA = wx.lib.scrolledpanel.ScrolledPanel(self.scroll, -1, style=wx.SIMPLE_BORDER, size=(300,200))
            panelA.SetupScrolling()
            panelA.SetBackgroundColour('#EEE111')
            panelB = wx.lib.scrolledpanel.ScrolledPanel(self.scroll, -1, style=wx.SIMPLE_BORDER, size=(200,200))
            panelB.SetupScrolling()
            panelB.SetBackgroundColour('#Eaa222')
            mainSizer.Add(panelA, 1, wx.ALL|wx.EXPAND, 5)
            mainSizer.Add(panelB, 1, wx.ALL|wx.EXPAND, 5)
            self.scroll.SetSizer(mainSizer)
    
    if __name__=='__main__':
        app = wx.App(0)
        frame = GUI().Show()
        app.MainLoop()
    

    Method 2: You can use the wx.lib.scrolledpanel.ScrolledPanel

    Example:

    import wx
    import wx.lib.scrolledpanel
    
    class GUI(wx.Frame):
        def __init__(self):
            wx.Frame.__init__(self, None, wx.ID_ANY, "Test app v1.0", style = wx.DEFAULT_FRAME_STYLE )
            self.Center()
            self.CreateStatusBar()
            mainSizer = wx.BoxSizer(wx.VERTICAL)
            mainPanel = wx.lib.scrolledpanel.ScrolledPanel(self, -1, style=wx.SIMPLE_BORDER, size=(400, 200))
            mainPanel.SetupScrolling()
            mainPanel.SetBackgroundColour('#00000')
            panelA = wx.lib.scrolledpanel.ScrolledPanel(mainPanel, -1, style=wx.SIMPLE_BORDER, size=(300,200))
            panelA.SetupScrolling()
            panelA.SetBackgroundColour('#EEE111')
            panelB = wx.lib.scrolledpanel.ScrolledPanel(mainPanel, -1, style=wx.SIMPLE_BORDER, size=(200,200))
            panelB.SetupScrolling()
            panelB.SetBackgroundColour('#Eaa222')
            mainSizer.Add(panelA, 1, wx.ALL|wx.EXPAND, 5)
            mainSizer.Add(panelB, 1, wx.ALL|wx.EXPAND, 5)
            mainPanel.SetSizer(mainSizer)
    
    if __name__=='__main__':
        app = wx.App(0)
        frame = GUI().Show()
        app.MainLoop()
    

    Output:

    Code output