Getting a control to expand on only one axis

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)

1-SIZER.A.png

1-SIZER.B.png

2-SIZERS.A.png

2-SIZERS.B.WITH-BUTTONS.png

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 ? }

What kind of assistance do you need? You can post to the wiki or I can
do it for you once you've got the text the way you want it.

···

On Jul 26, 4:41 pm, Ray Pasco <pas...@verizon.net> wrote:

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
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 ? }

-------------------
Mike Driscoll

Blog: http://blog.pythonlibrary.org