Thanks for both your replies.
I later stumbled across solution in a semi-desperate splattering of
sizer parameter values. I say “stumbled” because I have never found
a reasonably complete and coherent list of sizer rules in any of the
docs nor in any of the many examples with BoxSizers I have ever
seen.
I don't want to rant, but... The "UsingSizers" page on the
wxPyWiki is truly HORRIBLE ! It is the most confusing “explanation”
I have ever come across, anywhere, for any technical subject at all
! I am not exaggerating. Can creating a reasonably understandable
and complete sizer tutorial be that difficult ?
I now feel comfortable in getting BoxSizers to lay out anything in
any manner I can think of, at the moment. Time will tell.
More importantly, if anyone is willing, I would like write a new
tutorial using the sizing rules I have learned. This must be a small
group project. Checking it for validity must be done by several
others. Making this tutorial “look pretty” will have to be done by
some one else, too.
Ray Pasco
Here's an outline for BoxSizers I threw together.
SIZERS_TUTORIAL.TXT (7.4 KB)
2-TXTCTRLS_2-STATICTEXTS_1-SIZER.PY (2.09 KB)
2-TXTCTRLS_2-STATICTEXTS_2-SIZERS_2-BUTTONS.PY (3.19 KB)
···
SIZERS
Sizers are control positioning algorithms. As such they can not be
directly seen, but it’s effects are readily apparent. The
wx.BoxSizer is the most fundamental sizer and probably the most
used. Understanding its rules will go a long way to understanding
all the other more complex sizers.
The BoxSizer
The BoxSizer, unfortunately, is poorly named. A better one would be
“StackSizer”. It holds controls stacked in either the vertical or
horizontal directions, from top-to-bottom or left to-right,
respectively. When creating a BoxSizer, it must be declared with
either the wx.VERTICAL or wx.HORIZONTAL parameter. E.g.:
listControls_vertSizer = wx.BoxSizer( wx.VERTICAL )
Controls of nearly any type are inserted into the sizer
(top-to-bottom or right-to-left) using the .Add() method. The
general form is:
{sizer name}.Add( {control name},
proportion={an integer}
flag={a logical "OR" of many possible
positioning and padding flags},
[border={a positive integer}] ) # optional
padding border size
The last three parameters are optional, but it is unlikely that
“flag” positioning and/or spacing padding is not needed to achieve a
reasonable and acceptable appearance.
The proportion argument
A control such as a multi-line wx.TextCtrl can either
expandable=stretchable=grow-able along both its axes or have one or
both of its dimension be a fixed size. To be expandable along an
axis its axis dimension must be set to "-1’. [ ??? Does “0” have a
specific effect ? ]
The "proportion" parameter determines the size of the control in
relation to the size of all the other controls in that sizer along
the sizer’s declared axis. A proportion value of ‘0’ makes its
.Add()_ed control be “properly minimally” sized as is typically
desired with such a control as a wx.Button. A given proportion
integer value greater than 0 will cause that control to be attempted
to be stretched along the sizer’s axis as much as the wx.Frame or
wx.Window interior (client size) allows. The amount of expansion
depends on the interaction of all the other controls and whether
they are also trying to expand.
Each control with a proportion value >= 1 will divide up all the
possible expansion room in exact proportion to their given
proportion values less the room already claimed by the fixed,
minimally sized controls. So, axis room is allotted according to:
` wx.Window or wx.Frame Axis dimension (extent) =
Sum( (the fixed-sized controls [proportion = 0]) +
(the expanding controls [proportion >= 1])
)
`
[ ??? Can proportion be negative ? ]
A real-life example is in order. Let's make a wx.Frame with 4
controls: a wx.StaticText, a single-line wx.TextControl, another
wx.StaticText and another single-line wx.TextControl. The
wx.StaticText()_s have had their .BackGroundColour() set to
something other than the frame’s background color just so the extent
of the staticTexts can easily be seen. The frame looks like this:
{ Insert image of file 1-SIZER.A.png ]
{ insert 2-TXTCTRLS_2-STATICTEXTS_1-SIZER.PY here }
[ maybe the code should come first, then the image ]
For now, just note the order in which controls are added to the
sizer and what values are given for the “proportion” parameters.
This is pretty good for the first try. But, you probably will want
to tweak it in just a few ways. First, there needs to be empty
spaces to the left of the first StaticText and also to the right of
the second TextCtrl. This is easily done using:
allCtrls_horzSizer.AddSpacer( 15 )
... just before .Add()_ing the first StaticText and just after
.Add()_ing the last TextCtrl. The frame now looks like:
[ Insert image of file 1-SIZER.B.png ]
This was a small, be nice addition. Notice that when the frame's
right-hand border is stretched the 2 spacer’s “spaces” are
maintained. Since the 2 StaticText_'s were added to their sizer with
“proportion=0” their horizontal extent is fixed and is maintained
despite any frame resizing. The TextCtrls were added to their sizer
with “proportion=1”, so their individual extents are equal to each
other, but shrink or grow with changes in the frame’s horizontal
size/extent. So, now Spacers need to be added to the “Space
Equation” as fixed-sized elements. Their not “controls” in the wx
sense in that they have no properties or events of any kind except
for their dimension along their sizer’s axis.
` wx.Window or wx.Frame Axis dimension (extent) =
Sum( (the fixed-sized controls [proportion = 0] +
AddSpacer()_s) +
(the expanding controls [proportion >= 1])
)
`
Everything that takes up room in a Sizer has been accounted for,
except for another separate Sizer.
The 2nd try at layout is definitely better, but a major flaw still
exists: When the frame is vetically resized all the controls in the
sizer “float” up or down (vertically) in the middle of the frame.
If the frame is designed to be a fixed size this may not actually be
a detriment depending on whether you happen to like everything to be
automatically vertically centered.
If, instead, you want the controls pushed up near the top of the
frame client a new wx.VERTICAL sizer can enclose the existing
wx.HORIZONTAL sizer in order to adjust the inner sizer’s vertical
positioning. Adding an inner sizer to an outer sizer is very much
the same as just adding a control to a sizer. The modified code that
adds a 2nd sizer:
[ insert TXTCTRLS_2-STATICTEXTS_2-SIZERS.PY here ]
Et, voila ! Not bad bad at all. Now there's room at the bottom to
add other useful controls such as buttons or anything/everything
else you may want. So, let’s add a couple of buttons: “OK” and
“Cancel”.
{ insert additional code }
{ insert file image 2-SIZERS.B.WITH-BUTTONS.png }
This frame is getting to look like something useful. Once code to
handle the button events has been added this wx.Frame (a wx.Window
subclass ) is 95% on its way to becoming a custom popup window !
Actually modifying it to be a custom popup window deserves to be the
subject of separate tutorial.
Now that the basics for creating and adding to BoxSizers has been
covered, the slippery “flag” parameters need attention.
{ And so on ...
Should I continue ?
Is anyone willing to assist me ? }