wx.Frame.SetClientSize is causing child to re-size

I have a wx.Frame which I want to exactly fit one child Panel:

class DockingInfoFrame(DockingFrame):

def __init__(self, parent, title):
    DockingFrame.__init__(self, parent, title=title)
    self.childPanel = None
def ResizeToChild(self):
    [logger.info](http://logger.info)("DockingInfoFrame re-sizing to child's size of %s" % (
        self.childPanel.GetSize(),))
    if self.childPanel:
        self.SetClientSize(self.childPanel.GetSize())
def SetPanel(self, panel):
    if self.childPanel is not None:
        self.childPanel.Unbind(wx.EVT_SIZE, handler=self.OnChildSize)
        self.RemoveChild(self.childPanel)
    self.childPanel = panel
    if self.childPanel is not None:
        self.childPanel.Bind(wx.EVT_SIZE, self.OnChildSize)
        self.ResizeToChild()
def OnChildSize(self, event):
    logger.debug("DockingInfoFrame.OnChildSize fired with size %s",
                 event.GetSize())
    event.Skip()
    self.ResizeToChild()

In the child panel, I have some code where I calculate & set the size:

    sizingLogger.debug("InfoPanel re-sizing to %s", (W, H))
    self.SetSize((W, H))

This is what the logging output looks like:

gui.info_panel.sizing - DEBUG - InfoPanel re-sizing to (94, 245)

gui.GameFrame - DEBUG - DockingInfoFrame.OnChildSize fired with size (94, 245)

gui.GameFrame - INFO - DockingInfoFrame re-sizing to child’s size of (94, 245)

gui.GameFrame - DEBUG - DockingInfoFrame.OnChildSize fired with size (106, 245)

gui.GameFrame - INFO - DockingInfoFrame re-sizing to child’s size of (106, 245)

What seems to happen is that the .SetClientSize line is causing another child sizing event to be fired, this time with 12 extra pixels of width. This causes an ugly extra band on the panel which I want to remove. Why am I getting these extra pixels? Why is changing the client size of the Frame causing its child panel to get resized?

Thanks,

  • Claudiu

Claudiu Saftoiu wrote:

What seems to happen is that the .SetClientSize line is causing another
child sizing event to be fired, this time with 12 extra pixels of width.
This causes an ugly extra band on the panel which I want to remove. Why
am I getting these extra pixels? Why is changing the client size of the
Frame causing its child panel to get resized?

One of the built-in features of the wx.Frame class is that if it has only one child then in the frame's EVT_SIZE handler it will resize the child to fill the client area of the frame. If you want to disable that then you can bind the frame's EVT_SIZE to a handler that does something different (or nothing at all). I'm not sure about the extra 12 pixels or where it may be coming from, that does seem a bit odd.

Another solution that may meet your needs is to simply use self.Fit() to resize the frame to fit its contents. For this to work well you should give the frame a sizer to manage the layout of the child, and the child should either have a sizer of its own or have a minsize set.

···

--
Robin Dunn
Software Craftsman

Claudiu Saftoiu wrote:

What seems to happen is that the .SetClientSize line is causing another

child sizing event to be fired, this time with 12 extra pixels of width.

This causes an ugly extra band on the panel which I want to remove. Why

am I getting these extra pixels? Why is changing the client size of the

Frame causing its child panel to get resized?

One of the built-in features of the wx.Frame class is that if it has only one child then in the frame’s EVT_SIZE handler it will resize the child to fill the client area of the frame. If you want to disable that then you can bind the frame’s EVT_SIZE to a handler that does something different (or nothing at all). I’m not sure about the extra 12 pixels or where it may be coming from, that does seem a bit odd.

It seems that for some reason it was deciding its minimum size should be 106 pixels. Putting self.SetMinSize((10, 10)) in the constructor fixed the issues.

Another solution that may meet your needs is to simply use self.Fit() to resize the frame to fit its contents. For this to work well you should give the frame a sizer to manage the layout of the child, and the child should either have a sizer of its own or have a minsize set.

I couldn’t get sizers to work so I’ve been doing the layout manually, but the last thing you said there might be the reason. I made an ImagePanel to display a bitmap, but I wasn’t setting its min size, so the auto sizer layout was eating it up. Maybe I’ll revisit that.

In terms of using .Fit(), the docs suggest using .SetClientSize(child.GetSize()) instead, they say it’s more accurate.

Thanks for the reply!

  • Claudiu
···

On Thu, Mar 21, 2013 at 4:34 PM, Robin Dunn robin@alldunn.com wrote:

Claudiu Saftoiu wrote:

On Thu, Mar 21, 2013 at 4:34 PM, Robin Dunn <robin@alldunn.com

In terms of using .Fit(), the docs suggest using
.SetClientSize(child.GetSize()) instead, they say it's more accurate.

If you're using sizers then using Fit is easier IMO and accomplishes the same thing. Plus it doesn't depend on the child already being the correct size, only that it knows what its correct size is.

···

--
Robin Dunn
Software Craftsman