wxpythonwxwidgetswxnotebook

wxPython scrolledwindow in a notebook does not scroll


I want to have scrolled windows on tabs of a notebook. If the window is too small the contents should be scrollable. Everything is laid out correctly if the window is big enough. It also looks correctly when the window is too small to fit everything, but the scrollbars never appear, nor can I scroll with the mouse wheel. This is my minimum failing case:

#!/usr/bin/env python3
import wx

class MainWindow(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__ (self, parent, id = wx.ID_ANY, title = u"Title", pos = wx.DefaultPosition, size = wx.Size(800,480), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL)
        self.SetSizeHints(wx.DefaultSize, wx.DefaultSize)
        notebook = wx.Notebook(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, 0)
        
        for tab in range(0,3):
            scrolled_window = wx.ScrolledWindow(notebook, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.HSCROLL|wx.VSCROLL)
            sizer = wx.GridSizer(0, 5, 0, 0)
            scrolled_window.SetScrollRate(5, 5)
            scrolled_window.SetSizer(sizer)
            notebook.AddPage(scrolled_window, "Tab %d" % tab, False)
            scrolled_window.SetScrollbars(1, 1, 1, 1)
            
            for btn in range(0,50):
                button = wx.Button(scrolled_window, wx.ID_ANY, str(btn), wx.DefaultPosition, wx.DefaultSize, 0)
                button.SetMinSize((-1, 90))
                sizer.Add(button, 0, wx.ALL|wx.EXPAND, 5)
                sizer.Fit(scrolled_window)
                self.Layout()                
    
app = wx.App(False)
main_window = MainWindow(parent=None)
main_window.Show(True)
app.MainLoop()

Additionally I see this assertion fail (once for every tab or whenever I change the tab):

(scroll_bug.py:8990): Gtk-CRITICAL **: 09:02:58.514: gtk_box_gadget_distribute: assertion 'size >= 0' failed in GtkNotebook

Thanks for help


Solution

  • I'm not sure but the issue may be trying to use a ScrolledWindow as a subordinate child window within the notebook.
    A panel is a better fit.
    Try using a ScrolledPanel instead e.g.

    #!/usr/bin/env python3
    import wx
    import wx.lib.scrolledpanel as scrolled
    
    class MainWindow(wx.Frame):
        def __init__(self, parent):
            wx.Frame.__init__ (self, parent, id = wx.ID_ANY, title = u"Title", pos = wx.DefaultPosition, size = wx.Size(800,480), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL)
            self.SetSizeHints(wx.DefaultSize, wx.DefaultSize)
            self.panel = wx.Panel(self)
            notebook = wx.Notebook(self.panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, 0)
            
            for tab in range(0,3):
                scrolled_window = scrolled.ScrolledPanel(notebook, wx.ID_ANY)
                scrolled_window.SetupScrolling()
                notebook.AddPage(scrolled_window, "Tab %d" % tab, False)
                bsizer = wx.GridSizer(0, 5, 0, 0)            
                for btn in range(0,50):
                    button = wx.Button(scrolled_window, wx.ID_ANY, str(btn), wx.DefaultPosition, wx.DefaultSize, 0)
                    button.SetMinSize((-1, 90))
                    bsizer.Add(button, 0, wx.ALL|wx.EXPAND, 5)
                scrolled_window.SetSizer(bsizer)
    
            sizer = wx.BoxSizer(wx.VERTICAL)
            sizer.Add(notebook, 1, wx.ALL| wx.EXPAND, 5)
            self.panel.SetSizer(sizer)
            self.Layout()                
            self.Refresh()                
        
    app = wx.App(False)
    main_window = MainWindow(parent=None)
    main_window.Show(True)
    app.MainLoop()
    

    enter image description here