WxPython's ScrolledWindow element collapses to minimum size
Question: I am using a Panel within a Frame to display images (the GUI need to switch
between multiple panels and hence the hierarchy). As images should be
displayed in native size I used ScrolledWindow as the panel parent. The
scrolls do appear and work, but it causes the Panel to collapse to minimum
size and it needs to be resized using drag&drop every time. Is there a way
around this?

Below is a reduced version of the code, which shows the problem:

    
    
    import os
    import wx
    from wx.lib.pubsub import pub
    
    
    class Edit_Panel(wx.PyScrolledWindow):
        def __init__(self, parent):
            super(Edit_Panel, self).__init__(parent)
    
            # Display size
            width, height = wx.DisplaySize()
            self.photoMaxSize = height - 500
    
            # Loaded image
            self.loaded_image = None
    
            # Icons
            self.open_icon_id = 500
    
            # Generate panel
            self.layout()
    
        def layout(self):
            self.main_sizer = wx.BoxSizer(wx.VERTICAL)
    
            divider = wx.StaticLine(self, -1, style = wx.LI_HORIZONTAL)
            self.main_sizer.Add(divider, 0, wx.ALL | wx.EXPAND)
    
            self.toolbar = self.init_toolbar()
            self.main_sizer.Add(self.toolbar, 0, wx.ALL)
    
            img = wx.EmptyImage(self.photoMaxSize, self.photoMaxSize)
            self.image_control = wx.StaticBitmap(self, wx.ID_ANY,
                                                 wx.BitmapFromImage(img))
            self.main_sizer.Add(self.image_control, 0, wx.ALL | wx.CENTER, 5)
    
            self.image_label = wx.StaticText(self, -1, style = wx.ALIGN_CENTRE)
            self.main_sizer.Add(self.image_label, 0, wx.ALL | wx.ALIGN_CENTRE, 5)
    
            self.SetSizer(self.main_sizer)
    
            fontsz = wx.SystemSettings.GetFont(wx.SYS_SYSTEM_FONT).GetPixelSize()
            self.SetScrollRate(fontsz.x, fontsz.y)
            self.EnableScrolling(True, True)
    
        def init_toolbar(self):
            toolbar = wx.ToolBar(self)
            toolbar.SetToolBitmapSize((16, 16))
    
            open_ico = wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN, wx.ART_TOOLBAR, (16, 16))
            open_tool = toolbar.AddSimpleTool(self.open_icon_id, open_ico, "Open", "Open an Image Directory")
            handler = self.on_open_reference
            self.Bind(event = wx.EVT_MENU, handler = handler, source = open_tool)
    
            toolbar.Realize()
    
            return toolbar
    
        def on_open_reference(self, event, wildcard = None):
            if wildcard is None:
                wildcard = self.get_wildcard()
    
            defaultDir = '~/'
            dbox = wx.FileDialog(self, "Choose an image to display", defaultDir = defaultDir, wildcard = wildcard, style = wx.OPEN)
    
            if dbox.ShowModal() == wx.ID_OK:
                file_name = dbox.GetPath()
    
                # load image
                self.load_image(image = file_name)
    
            dbox.Destroy()
    
        def get_wildcard(self):
            wildcard = 'Image files (*.jpg;*.png;*.bmp)|*.png;*.bmp;*.jpg;*.jpeg'
            return wildcard
    
        def load_image(self, image):
            self.loaded_image = image
    
            # Load image
            img = wx.Image(image, wx.BITMAP_TYPE_ANY)
    
            # Label image name
            image_name = os.path.basename(image)
            self.image_label.SetLabel(image_name)
    
            # scale the image, preserving the aspect ratio
            scale_image = True
            if scale_image:
                W = img.GetWidth()
                H = img.GetHeight()
                if W > H:
                    NewW = self.photoMaxSize
                    NewH = self.photoMaxSize * H / W
                else:
                    NewH = self.photoMaxSize
                    NewW = self.photoMaxSize * W / H
                img = img.Scale(NewW, NewH)
    
            self.image_control.SetBitmap(wx.BitmapFromImage(img))
    
            # Render
            self.main_sizer.Layout()
    
            self.main_sizer.Fit(self)
            self.Refresh()
    
            pub.sendMessage("resize", msg = "")
    
    
    class Viewer_Frame(wx.Frame):
        def __init__(self, parent, id, title):
            super(Viewer_Frame, self).__init__(parent = parent, id = id, title = title)
    
            # Edit panel
            self.edit_panel = Edit_Panel(self)
    
            # Default panel
            self.main_panel = self.edit_panel
    
            # Render frame
            self.render_frame()
    
            # Subscription to re-render
            pub.subscribe(self.resize_frame, ("resize"))
    
        def render_frame(self):
            # Main Sizer
            self.main_sizer = wx.BoxSizer(wx.VERTICAL)
    
            # Add default sizer
            self.main_sizer.Add(self.main_panel, 1, wx.EXPAND)
    
            # Render
            self.SetSizer(self.main_sizer)
            self.Show()
            self.main_sizer.Fit(self)
            self.Center()
    
    
        def resize_frame(self, msg):
            self.main_sizer.Fit(self)
    
    
    if __name__ == "__main__":
        app = wx.App(False)
        frame = Viewer_Frame(parent = None, id = -1, title = 'Toolkit')
        app.MainLoop()
    


Answer: You're calling `Fit()`, so you're explicitly asking the panel to fit its
contents, but you don't specify the min/best size of this contents anywhere
(AFAICS, there is a lot of code here, so I could be missing something).

If you want to use some minimal size for the panel, just set it using
`SetMinSize()`.

