Buttons and Sizers

Hello,

I’m just starting out with sizers; I’ve hit a problem placing buttons using a box sizer. I can place the buttons in a panel using absolute positioning and then put that panel in a sizer but I can’t add the buttons directly to the sizer.

I am following a tutorial at http://www.zetcode.com/wxpython/layout/ and in one of the examples (attached ‘tutorial_example.py’) they add buttons directly to a sizer (section at end with hbox5).
I’ve fiddled with various different combinations but can’t get it to work for me.

I’ve attached my working code (‘properties.py’ – using absolute position for the buttons) , what I would like to know is how can I achieve the same thing using sizers instead of absolute positioning with the buttons?

Is using sizers for buttons the best way to position them?

Thanks in advance

properties.py (1.9 KB)

tutorial_example.py (2.12 KB)

Hello,

I’m just starting out with sizers; I’ve hit a problem placing buttons using

a box sizer. I can place the buttons in a panel using absolute positioning
and then put that panel in a sizer but I can’t add the buttons directly to
the sizer.

Hello. First off, keep in mind that buttons are not special in regards to sizers. In fact, as far as I know, no visual object on the GUI is special with regards to sizers. They’ll manage the layout for any visible thing you put in them.

I am following a tutorial at http://www.zetcode.com/wxpython/layout/ and in
one of the examples (attached ‘tutorial_example.py’) they add buttons

directly to a sizer (section at end with hbox5).
I’ve fiddled with various different combinations but can’t get it to work
for me.

I’ve attached my working code (‘properties.py’ – using absolute position

for the buttons) , what I would like to know is how can I achieve the same
thing using sizers instead of absolute positioning with the buttons?

See below…

Is using sizers for buttons the best way to position them?

Definitely. It’s the best way to position anything in wxPython. Sizers make it such that your layout will look good on other platforms and setups with other resolutions than yours, allow for things to dynamically expand as you resize the frame (very important for look and feel) and also makes it easy for things to look lined-up and neat

To understand box sizers, think in terms of the vertical ones managing a vertical stack of things and the horizontal ones managing a horizontal row of things. Then realize that the “things” can themselves be sizers. So often a pattern one might use is a vertical boxsizer laying out a stack of rows, with each row being managed by a horizontal box sizer. See attached image. (With other types of sizers, you can also do something like this).

I’ve changed your code to have it do what you were trying to do. Basically, the mistake you made begins at line 35:

hbox2.Add(panel3,0)

You add panel3 to a horizontal boxSizer, as if you were going to make a “row” of visible items, starting with panel3 as the first thing in that row. But that’s not what you want. You want panel3 to be shown under the two large areas at top, and you want the buttons to form a row within panel3. So, panel3 has to be positioned with a vertical box sizer that will just add it as the lone item in the final row (under the two large areas). So, add it to the vbox sizer:

vbox.Add(panel3,0,flag=wx.ALIGN_CENTER)

Then, the buttons need to be in some horizontal box sizer that is associated with panel3. So the two steps are: 1) Associate a horizontal box sizer to panel3:

panel3.SetSizer(hbox2)

and then 2) Add the buttons to this hbox2 sizer:

hbox2.Add(button1,0)  
hbox2.Add(button2,0, wx.LEFT | wx.BOTTOM , 5)  

I think this gets it to about where you were aiming. I also moved SetSizerAndFit() to the end, since I thought that it may need to be called after all your laying-out is done so that it knows how much it has to fit to. This is a start, but you’ll see that you can make better layouts than this (just try removing the 20 point borders, for example).

There are a number of tutorials out there on wxPython sizers that you can get to by Googling. Sizers are tricky to think in terms of at first. Stay with it, and it will pay off.

Che

propertiesEdited.py (2.07 KB)

···

On Wed, Jul 14, 2010 at 10:00 PM, Seb S sebas.home1@gmail.com wrote:

If you don't find the tutorials on the wiki or my blog sufficiently
informative, post back with what you want to know about sizers and I'm
sure we'll be able to help you. Maybe I'll even write up a new
tutorial!

···

On Jul 14, 11:04 pm, C M <cmpyt...@gmail.com> wrote:

On Wed, Jul 14, 2010 at 10:00 PM, Seb S <sebas.ho...@gmail.com> wrote:
> Hello,

> I'm just starting out with sizers; I've hit a problem placing buttons
using
> a box sizer. I can place the buttons in a panel using absolute
positioning
> and then put that panel in a sizer but I can't add the buttons directly
to
> the sizer.

Hello. First off, keep in mind that buttons are not special in regards to
sizers. In fact, as far as I know, no visual object on the GUI is special
with regards to sizers. They'll manage the layout for any visible thing you
put in them.

> I am following a tutorial athttp://www.zetcode.com/wxpython/layout/and
in
> one of the examples (attached 'tutorial_example.py') they add buttons
> directly to a sizer (section at end with hbox5).
> I've fiddled with various different combinations but can't get it to work
> for me.

> I've attached my working code ('properties.py' -- using absolute position
> for the buttons) , what I would like to know is how can I achieve the same
> thing using sizers instead of absolute positioning with the buttons?

See below...

> Is using sizers for buttons the best way to position them?

Definitely. It's the best way to position anything in wxPython. Sizers
make it such that your layout will look good on other platforms and setups
with other resolutions than yours, allow for things to dynamically expand as
you resize the frame (very important for look and feel) and also makes it
easy for things to look lined-up and neat

To understand box sizers, think in terms of the vertical ones managing a
vertical stack of things and the horizontal ones managing a horizontal row
of things. Then realize that the "things" can themselves be sizers. So
often a pattern one might use is a vertical boxsizer laying out a stack of
rows, with each row being managed by a horizontal box sizer. See attached
image. (With other types of sizers, you can also do something like this).

I've changed your code to have it do what you were trying to do. Basically,
the mistake you made begins at line 35:

hbox2.Add(panel3,0)

You add panel3 to a horizontal boxSizer, as if you were going to make a
"row" of visible items, starting with panel3 as the first thing in that row.
But that's not what you want. You want panel3 to be shown under the two
large areas at top, and you want the buttons to form a row *within* panel3.
So, panel3 has to be positioned with a vertical box sizer that will just
add it as the lone item in the final row (under the two large areas). So,
add it to the vbox sizer:

vbox.Add(panel3,0,flag=wx.ALIGN_CENTER)

Then, the buttons need to be in some horizontal box sizer that is associated
with panel3. So the two steps are: 1) Associate a horizontal box sizer to
panel3:

panel3.SetSizer(hbox2)

and then 2) Add the buttons to this hbox2 sizer:

hbox2.Add(button1,0)
hbox2.Add(button2,0, wx.LEFT | wx.BOTTOM , 5)

I think this gets it to about where you were aiming. I also moved
SetSizerAndFit() to the end, since I thought that it may need to be called
after all your laying-out is done so that it knows how much it has to fit
to. This is a start, but you'll see that you can make better layouts than
this (just try removing the 20 point borders, for example).

There are a number of tutorials out there on wxPython sizers that you can
get to by Googling. Sizers are tricky to think in terms of at first. Stay
with it, and it will pay off.

Che

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

Blog: http://blog.pythonlibrary.org

There are a number of tutorials out there on wxPython sizers that you can
get to by Googling. Sizers are tricky to think in terms of at first. Stay
with it, and it will pay off.

I'd also suggest to browse the demo sources and see how include
PyCrust/InspectionTool: they are really precious to understand what's going on
and also interact with the gui objects

···

--
Beauty is a pair of shoes that makes you wanna die

I would like to see the box sizer tutorial, http://wiki.wxpython.org/AnotherTutorial#wx.BoxSizer,
enhanced in the use of proportion, wx.EXPAND and Add( size-
tuple, ...).

For example, if these lines had been the guts of the the layout3.py
example I wouldn't have burned a couple of days last week trying to
get a button to stick the right end of a horizontal box sizer. These
lines turn that example into a window with 3 buttons that maintain
their sizes and relative positions while the window is resized.

        self.SetMinSize( (200,100) )

        b1 = wx.Button(panel, -1, 'Button1', style=wx.BU_EXACTFIT)
        b2 = wx.Button(panel, -1, 'Button2', style=wx.BU_EXACTFIT)
        b3 = wx.Button(panel, -1, 'Button3', style=wx.BU_EXACTFIT)

        box.Add(b1, 0, wx.ALIGN_TOP|wx.ALL, 5 )
        box.Add((1, -1), 1, wx.EXPAND )
        box.Add(b2, 0, wx.ALIGN_BOTTOM )
        box.Add((1, -1), 1, wx.EXPAND )
        box.Add(b3, 0, wx.ALIGN_CENTER_VERTICAL )

Also, I think I'm correct in saying that the wx.ALIGN_xxx flags only
effect the opposite dimension. That is that wx.ALIGN_{RIGHT|LEFT|
CENTER_HORIZONTAL} have no effect on a horizontal box sizer and vice
versa. Yet there are many instances of this usage in the examples. I
think this is misleading.

Al Mansur

···

On Jul 15, 7:11 am, Mike Driscoll <kyoso...@gmail.com> wrote:

If you don't find the tutorials on the wiki or my blog sufficiently
informative, post back with what you want to know about sizers and I'm
sure we'll be able to help you. Maybe I'll even write up a new
tutorial!

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

Blog: http://blog.pythonlibrary.org

I'll try to remember to take a look at that...I was actually thinking
of the specific sizer tutorials. Such as this one:

http://wiki.wxpython.org/BoxSizerTutorial

or SizerTutorials - wxPyWiki

Those are more advanced. The alignment stuff is tricky:

ALIGN_CENTER or better, wx.CENTER, will center horizontally in a
horizontal BoxSizer and vertically in a vertical BoxSizer. To have one
button on the left and one on the right side, you'll need a spacer
between the two. Otherwise, the sizer will size to the smallest amount
needed to hold the widgets. Thus, the buttons are actually aligned
correctly in the sizer, but not visually. You can use the Widget
Inspection Tool to see this in action...

I should probably write up something about the alignment issues
though.

···

On Jul 18, 5:43 pm, Al <alman...@rusnam.org> wrote:

On Jul 15, 7:11 am, Mike Driscoll <kyoso...@gmail.com> wrote:

> If you don't find the tutorials on the wiki or my blog sufficiently
> informative, post back with what you want to know about sizers and I'm
> sure we'll be able to help you. Maybe I'll even write up a new
> tutorial!

> -------------------
> Mike Driscoll

> Blog: http://blog.pythonlibrary.org

I would like to see the box sizer tutorial,http://wiki.wxpython.org/AnotherTutorial#wx.BoxSizer,
enhanced in the use of proportion, wx.EXPAND and Add( size-
tuple, ...).

For example, if these lines had been the guts of the the layout3.py
example I wouldn't have burned a couple of days last week trying to
get a button to stick the right end of a horizontal box sizer. These
lines turn that example into a window with 3 buttons that maintain
their sizes and relative positions while the window is resized.

    self\.SetMinSize\( \(200,100\) \)

    b1 = wx\.Button\(panel, \-1, &#39;Button1&#39;, style=wx\.BU\_EXACTFIT\)
    b2 = wx\.Button\(panel, \-1, &#39;Button2&#39;, style=wx\.BU\_EXACTFIT\)
    b3 = wx\.Button\(panel, \-1, &#39;Button3&#39;, style=wx\.BU\_EXACTFIT\)

    box\.Add\(b1,      0, wx\.ALIGN\_TOP|wx\.ALL, 5 \)
    box\.Add\(\(1, \-1\), 1, wx\.EXPAND \)
    box\.Add\(b2,      0, wx\.ALIGN\_BOTTOM \)
    box\.Add\(\(1, \-1\), 1, wx\.EXPAND \)
    box\.Add\(b3,      0, wx\.ALIGN\_CENTER\_VERTICAL \)

Also, I think I'm correct in saying that the wx.ALIGN_xxx flags only
effect the opposite dimension. That is that wx.ALIGN_{RIGHT|LEFT|
CENTER_HORIZONTAL} have no effect on a horizontal box sizer and vice
versa. Yet there are many instances of this usage in the examples. I
think this is misleading.

Al Mansur

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

Blog: http://blog.pythonlibrary.org

Sizer spacer example (sizer.AddSpacer) :

class FnbPanel_1( wx.Panel ) :
    """ The first notebook page """

    def __init__( self, parent ) :

        wx.Panel.__init__( self, parent=parent, id=-1 )

        txtCtrl_1 = wx.TextCtrl( self, -1, "11111" )
        txtCtrl_2 = wx.TextCtrl( self, -1, "22222" )

        panelVert_sizer = wx.BoxSizer( wx.VERTICAL ) # no "border"
flags specified.
        panelVert_sizer.AddSpacer( 15 ) # at the panel top edge
        # The padding value -1 is ignored because the sizer has no
"border" flags enabled.
        panelVert_sizer.Add( txtCtrl_1, 0, wx.CENTER, -1 )
        panelVert_sizer.AddSpacer( 15 )
        panelVert_sizer.Add( txtCtrl_2, 0, wx.CENTER, -1 )

        self.SetSizer( panelVert_sizer )

    #end __init__

#end FnbPanel_1 class

···

On Jul 19, 11:31 am, Mike Driscoll <kyoso...@gmail.com> wrote:

On Jul 18, 5:43 pm, Al <alman...@rusnam.org> wrote:

> On Jul 15, 7:11 am, Mike Driscoll <kyoso...@gmail.com> wrote:

> > If you don't find the tutorials on the wiki or my blog sufficiently
> > informative, post back with what you want to know about sizers and I'm
> > sure we'll be able to help you. Maybe I'll even write up a new
> > tutorial!

> > -------------------
> > Mike Driscoll

> > Blog: http://blog.pythonlibrary.org

> I would like to see the box sizer tutorial,http://wiki.wxpython.org/AnotherTutorial#wx.BoxSizer,
> enhanced in the use of proportion, wx.EXPAND and Add( size-
> tuple, ...).

> For example, if these lines had been the guts of the the layout3.py
> example I wouldn't have burned a couple of days last week trying to
> get a button to stick the right end of a horizontal box sizer. These
> lines turn that example into a window with 3 buttons that maintain
> their sizes and relative positions while the window is resized.

> self.SetMinSize( (200,100) )

> b1 = wx.Button(panel, -1, 'Button1', style=wx.BU_EXACTFIT)
> b2 = wx.Button(panel, -1, 'Button2', style=wx.BU_EXACTFIT)
> b3 = wx.Button(panel, -1, 'Button3', style=wx.BU_EXACTFIT)

> box.Add(b1, 0, wx.ALIGN_TOP|wx.ALL, 5 )
> box.Add((1, -1), 1, wx.EXPAND )
> box.Add(b2, 0, wx.ALIGN_BOTTOM )
> box.Add((1, -1), 1, wx.EXPAND )
> box.Add(b3, 0, wx.ALIGN_CENTER_VERTICAL )

> Also, I think I'm correct in saying that the wx.ALIGN_xxx flags only
> effect the opposite dimension. That is that wx.ALIGN_{RIGHT|LEFT|
> CENTER_HORIZONTAL} have no effect on a horizontal box sizer and vice
> versa. Yet there are many instances of this usage in the examples. I
> think this is misleading.

> Al Mansur

I'll try to remember to take a look at that...I was actually thinking
of the specific sizer tutorials. Such as this one:

BoxSizerTutorial - wxPyWiki

orhttp://wiki.wxpython.org/SizerTutorials

Those are more advanced. The alignment stuff is tricky:

ALIGN_CENTER or better, wx.CENTER, will center horizontally in a
horizontal BoxSizer and vertically in a vertical BoxSizer. To have one
button on the left and one on the right side, you'll need a spacer
between the two. Otherwise, the sizer will size to the smallest amount
needed to hold the widgets. Thus, the buttons are actually aligned
correctly in the sizer, but not visually. You can use the Widget
Inspection Tool to see this in action...

I should probably write up something about the alignment issues
though.

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

Blog: http://blog.pythonlibrary.org

Thanks. I found the AddStretchSpacer() and Add( size, variants as
well.
I also found an odd interaction between wx.EXPAND and AddStretchSpacer
(and possibly any use of proportion=1).

        lab_p = wx.StaticText( self, -1, "Account Directory Path:" )
        but_p = wx.Button( self, -1, "Browse", style=wx.BU_EXACTFIT )
        box_lb = wx.BoxSizer( wx.HORIZONTAL )
        box_lb.Add( lab_p, 0, wx.ALL|wx.ALIGN_BOTTOM, 1 )
        box_lb.AddStretchSpacer( prop=1 )
        box_lb.Add( but_p, 0, wx.ALL, 1 )

        txt_p = autil.text_field( self, "", text_len=30 ) # makes a
TextCtrl 30 W's long
        box_p = wx.BoxSizer( wx.VERTICAL )
        box_p.Add( box_lb, 0, wx.ALL|wx.EXPAND, 1 ) # <-- expand
needed for stretch to work
        box_p.Add( txt_p, 0, wx.ALL, 1 )

        box_pa = wx.BoxSizer( wx.HORIZONTAL )
        box_pa.AddStretchSpacer( prop=1 )
        box_pa.Add( box_p, 0, wx.ALL|wx.ALIGN_RIGHT, 1 )

        sizer.Add( box_pa, 0, wx.ALL|wx.EXPAND, 1 ) # <-- expand
needed for stretch to work

Until I put those 2 wx.EXPANDs in there neither stretch did anything.

Al

···

On Jul 19, 9:52 am, WinCrazy <pas...@verizon.net> wrote:

Sizer spacer example (sizer.AddSpacer) :

class FnbPanel_1( wx.Panel ) :
""" The first notebook page """

def \_\_init\_\_\( self, parent \) :

    wx\.Panel\.\_\_init\_\_\( self, parent=parent, id=\-1 \)

    txtCtrl\_1 = wx\.TextCtrl\( self, \-1, &quot;11111&quot; \)
    txtCtrl\_2 = wx\.TextCtrl\( self, \-1, &quot;22222&quot; \)

    panelVert\_sizer = wx\.BoxSizer\( wx\.VERTICAL \)    \# no &quot;border&quot;

flags specified.
panelVert_sizer.AddSpacer( 15 ) # at the panel top edge
# The padding value -1 is ignored because the sizer has no
"border" flags enabled.
panelVert_sizer.Add( txtCtrl_1, 0, wx.CENTER, -1 )
panelVert_sizer.AddSpacer( 15 )
panelVert_sizer.Add( txtCtrl_2, 0, wx.CENTER, -1 )

    self\.SetSizer\( panelVert\_sizer \)

\#end \_\_init\_\_

#end FnbPanel_1 class