Dynamic resize of StaticBitmap

In my application I have a StaticBitmap in a vertical BoxSizer. The application allows the user to set a new bitmap and the code does show the new bitmap. However, if the new bitmap is larger than the original bitmap I haven’t been able to find a way to force the sizer to update its layout so that the StaticBitmap is not partly obscured by the next control in the sizer. I have tried varied combinations of Refresh(), Update(), Layout(), Hide() and Show() but none of my attempts made any difference. If I manually drag the bottom edge of the frame downwards, then the layout does get updated and the StaticBitmap is no longer obscured.

Here is a simple example that shows the problem:

import wx

class MyFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)
        self.SetSize((400, 220))
        self.SetTitle("Test Dynamic Resize")
        self.main_panel = wx.Panel(self, wx.ID_ANY)
        self.main_sizer = wx.BoxSizer(wx.VERTICAL)
        self.static_bitmap = wx.StaticBitmap(self.main_panel,
                                             wx.ID_ANY,
                                             wx.ArtProvider.GetBitmap(wx.ART_GO_HOME,
                                                                      wx.ART_OTHER,
                                                                      (32, 32)))
        self.main_sizer.Add(self.static_bitmap, 0, 0, 0)
        self.combo_box = wx.ComboBox(self.main_panel, wx.ID_ANY, choices=[], style=wx.CB_DROPDOWN)
        self.main_sizer.Add(self.combo_box, 0, 0, 0)
        bottom_sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.main_sizer.Add(bottom_sizer, 0, wx.BOTTOM | wx.EXPAND | wx.TOP, 5)
        bottom_sizer.Add((20, 20), 1, wx.EXPAND, 0)
        self.enlarge_button = wx.Button(self.main_panel, wx.ID_ANY, "Enlarge")
        bottom_sizer.Add(self.enlarge_button, 0, 0, 0)
        bottom_sizer.Add((20, 20), 1, wx.EXPAND, 0)
        self.close_button = wx.Button(self.main_panel, wx.ID_ANY, "Close")
        bottom_sizer.Add(self.close_button, 0, 0, 0)
        bottom_sizer.Add((20, 20), 1, wx.EXPAND, 0)
        self.main_panel.SetSizer(self.main_sizer)
        self.Layout()

        self.Bind(wx.EVT_BUTTON, self.onEnlarge, self.enlarge_button)
        self.Bind(wx.EVT_BUTTON, self.onClose,   self.close_button)


    def onEnlarge(self, _event):

        bitmap = wx.ArtProvider.GetBitmap(wx.ART_GO_HOME, wx.ART_OTHER, (64, 64))
        self.static_bitmap.SetBitmap(bitmap)


    def onClose(self, _event):

        self.Destroy()



class MyApp(wx.App):
    def OnInit(self):
        self.frame = MyFrame(None, wx.ID_ANY, "")
        self.SetTopWindow(self.frame)
        self.frame.Show()
        return True


if __name__ == "__main__":
    app = MyApp(0)
    app.MainLoop()

When you click on the ‘Enlarge’ button the bitmap is replaced with the same image but at twice the size. However, the bottom half is then obscured by the ComboBox. If I manually stretch the frame vertically, the layout gets updated and the controls are spaced out correctly so that the bitmap is no longer obscured.

How can I get the sizer to update its layout, programmatically?

I am using wxPython 4.0.1 (gtk3) and Python 3.6.9 on Linux Mint 19.3

Add

    self.main_panel.Layout()

as last line in onEnlarge.

1 Like

Thank you! Somehow, in all my attempts to get it to work, I had forgotten all about the panel. It also works fine in the real application.
Cheers!