wxPython minimal size of Frame with a Panel
Question: wxpython 2.8.11.0, python 2.7

If i put some `Sizer` with some controls directly into a `Frame` like

    
    
    import wx
    
    app=wx.App()
    
    frm = wx.Frame(None, title='title')
    
    sizer = wx.BoxSizer(wx.HORIZONTAL)
    sizer.Add(wx.SpinCtrl(frm))
    sizer.Add(wx.SpinCtrl(frm))
    
    frm.SetSizerAndFit(sizer)
    frm.Show()
    
    app.MainLoop()
    

the `Frame` will automagically have a correct minimum size to contain the
`Sizer` and it is not possible to make it smaller. If there is a `Panel` in
between (as needed for tabbing between controls) this does not work, the
window can be made too small.

    
    
    import wx
    
    app=wx.App()
    
    frm = wx.Frame(None, title='title')
    pan = wx.Panel(frm)
    
    sizer = wx.BoxSizer(wx.HORIZONTAL)
    sizer.Add(wx.SpinCtrl(pan))
    sizer.Add(wx.SpinCtrl(pan))
    
    pan.SetSizerAndFit(sizer)
    frm.Show()
    
    app.MainLoop()
    

Additionally `frm.Fit()` and `frm.SetMinSize(frm.GetEffectiveMinSize())` are
required to get the same behavior. Full Code:

    
    
    import wx
    
    app=wx.App()
    
    frm = wx.Frame(None, title='title')
    pan = wx.Panel(frm)
    
    sizer = wx.BoxSizer(wx.HORIZONTAL)
    sizer.Add(wx.SpinCtrl(pan))
    sizer.Add(wx.SpinCtrl(pan))
    
    pan.SetSizerAndFit(sizer)
    frm.Fit()
    frm.SetMinSize(frm.GetEffectiveMinSize())
    frm.Show()
    
    app.MainLoop()
    

I am okay with `frm.Fit()`, but i dislike
`frm.SetMinSize(frm.GetEffectiveMinSize())`. Isn't there a better solution so
that the `Frame` automatically considers the minimum size of the `Panel` just
like with the `Sizer` before? I'm considered with what happens if the
`EffectiveMinSize` changes after another control is added to the sizer.

**Edit:** Apparently

    
    
    panel.SetSizerAndFit(sizer)
    frm.Fit()
    frm.SetMinSize(frm.GetEffectiveMinSize())
    

should be replaced by

    
    
    panel.SetSizer(sizer)
    sizer.SetSizeHints(frm)
    

which looks somewhat cleaner. So in total this looks like

    
    
    import wx
    
    app=wx.App()
    
    frm = wx.Frame(None, title='title')
    pan = wx.Panel(frm)
    
    sizer = wx.BoxSizer(wx.HORIZONTAL)
    sizer.Add(wx.SpinCtrl(pan))
    sizer.Add(wx.SpinCtrl(pan))
    
    pan.SetSizer(sizer)
    sizer.SetSizeHints(frm)
    frm.Show()
    
    app.MainLoop()
    

Is this the preferred way to do this?

If widgets are added later on even the first approach with the `Sizer`
directly on the `Frame` doesn't get it right without intervention, so i think
that is a totally different question.


Answer: The most elegant way (IMHO) is given in phineas' answer. It is slightly
inefficient to have an extra otherwise unneeded sizer but I don't think it can
really be noticeable.

Some people do call `SetSizeHints()` manually, as in your last example, and
this works as well and might be more clear (whenever I use an extra sizer I
feel the need to leave a comment explaining why it shouldn't be removed).

Unfortunately there is no better way and I am not sure if we can even add one
because you need to do something with all of the panel, the sizer and the
frame and this means that you can't do it with a single method call without
passing unrelated parameters to it. I.e. we could have something like

    
    
    panel.SetSizerAndFitParent(sizer, frame);
    

but it's not really clear whether this would be better.

