I’m created a simple test wx.Window composed of 2 fixed sized and one
stretchable panels. the widget Window does properly stretch to its
parents Client size. But, in Window’s parent Frame, the sizer that is
supposed to control the Window’s vertical centering doesn’t seem to have
any effect whatever. (I threw in the StaticText just to see if
/frmPnl_vSzr/ would position it, but no luck there, either.) So, my 2
questions are:
1 - What doesn’t /frmPnl_vSzr / work at all ?
First things first. Go down to the local tattoo parlor and have them inscribe the following on some prominent part of your anatomy. “The WIT is your friend. Use the WIT Ray, use the WIT. http://wiki.wxpython.org/Widget_Inspection_Tool” If you had used the WIT you would have seen your PanelsWindow in the widget tree twice,
Actually, PanelsWindow is shown only once in the WIT, but its 3 child panels are shown in 2 different nameless sizers. Since sizers are often Added to other sizers I didn’t think that this was a problem.
The WIT has a serious shortcoming (to me) in that it doesn’t name any child controls or sizers within each class (which is named). To display Panel (“panel”) is redundant and seems pointless. Why doesn’t it show something like fixedPnlA (Panel), instead ?
once because of traversing the parent-child hierarchy, and the 2nd time because it was in a sizer that was connected to the wrong place. (See next paragraph.)
Where in The Official wxPython Sizer Guidebook does it say :
“You can not have one window’s [control’s] sizer contain another window’s [control’s] sizer.” ? I’ve never seen this stated anywhere.
2 - Is there a way that the parent can, instead, Add() the child Window
directly to /frmPnl_vSzr/ rather than adding its sizer// ?
Second, this is your problem. You can not have one window’s sizer contain another window’s sizer. But it can and should contain (and manage) the child window itself. So instead of
frmPnl_vSzr.Add( self.panelsWin.vSzr, proportion=0, flag=0 )
just use
frmPnl_vSzr.Add( self.panelsWin, proportion=0, flag=0 )
Next problem. The built-in layout is triggered in a window’s default EVT_SIZE handler. If you bind a handler for EVT_SIZE and don’t call Skip then the default layout will not happen.
In which controls is it true that “The built-in [auto-] layout is triggered in [the control’s] default EVT_SIZE handler” ?
Next problem. wx.Window does not do auto-layout (because not all of its subclasses should do it) however since you’ve bound an EVT_SIZE handler for PanelsWindow that calls Layout then you’ve worked around that issue. (You could just use wx.Panel as a base class instead and avoid the problem entirely.) However in that handler you are also resetting the size to match the parent’s size, but this window is being managed by its parent’s sizer, so the child window is effectively saying f-you to its parent and doing whatever it wants instead of following the parent’s suggestions or desired intent. (Sounds just like a teenager, eh?) If you want a class to have limits on the size when used with sizers then you can do things like SetMinSize or implement DoGetBestSize, but for functionality like “match the parent’s width” you should just let the parent (or its sizer) take care of that for you. The child should not need to know details about the parent like that.
My specific goal is to make the child class have the ability to be “self-sizing” in that this class should automatically expand to the parent client’s width without needing any parent intervention. This would make the child self-contained and much easier to use in that the parent would not need to use either a sizer for it or have to set its width “manually”. That I did it wrong was obvious, but why it was wrong in particular was very unclear to me, especially since I intentionally made it such a simple app.
Is this possible using wxPython ?
This is why I put an EVT_SIZE handler in the child class. When this failed miserably I added an EVT_SIZE handler in the parent class. This was the only way I could get anything to display even partially correctly.
Finally, since you set the size of the frame and frmPanel at the beginning before they have sizers, and since that size is not going to change initially when shown then there will not be an initial size event to do a layout, so you need to do something to help it do that initial layout. You tried calling self.Layout, but since it is self.frmPanel that has the sizer and the content then that is where the call to Layout should be. And since that Layout will change the size of self.panelsWin then there is no need to explicitly send it a size event.
OK, so is the rule : The widget that is being managed by the highest level sizer within a class should always call Layout() ?
In the attachment I’ve marked the lines that I’ve removed with a leading ## and the lines that I’ve added with a trailing ##.
–
Robin Dunn
Software Craftsman
http://wxPython.org
Thanks again,
Ray Pasco
···
On Fri, Aug 19, 2011 at 10:22 PM, Robin Dunn robin@alldunn.com wrote:
On 8/18/11 11:02 PM, Ray Pasco wrote: