sizer parent and the need to Add

I'm trying to leverage the half hour I just wasted tracking down a silly bug in my newbie wxPython code, to gain a deeper understanding. The symptom was that the several items I had added to a vertical BoxSizer were all appearing on top of one another, rather than stacked vertically as I expected. The problem turned out to be that I was passing "self" as the parent to each item's constructor, rather than the sizer.

Now I'm wondering: why must we both (1) specify the sizer as the parent, and (2) explicitly add the item to the sizer? Would there ever be a case where you would not want to add the item to its parent sizer?

I know (or think I know) that the sized_controls sizers (like SizedPanel) automatically add their children to themselves, but I need to use a simple BoxSizer here (or so I believe). Why don't all sizers do this?

Thanks,
- Joe

Doh -- it's late. I meant that I needed to pass the main panel of the window -- the one the sizer sizes -- as the parent.

This brings up a deeper issue: what exactly is a "panel" and when do I need one? Why can't I set a sizer for the frame itself? When would I create more than one panel for a window? If I do so, do they have any visible UI on any platform?

And yes, I've been through the wxPython tutorials I could find, and I'm thankful to them for my ability to create anything at all with it... but I'm still reciting a lot of incantations without fully understanding what I'm doing. Any help gaining that deeper understanding would be greatly appreciated.

Thanks,
- Joe

···

On Nov 17, 2008, at 9:46 PM, Joe Strout wrote:

The problem turned out to be that I was passing "self" as the parent to each item's constructor, rather than the sizer.

Joe Strout wrote:

Doh -- it's late. I meant that I needed to pass the main panel of the window -- the one the sizer sizes -- as the parent.

I was wondering about that...

This brings up a deeper issue: what exactly is a "panel"

It is a Window on which one can put other Controls/Windows.

and when do I need one?

when you want to group a bunch of controls that work together in some way.

Why can't I set a sizer for the frame itself?

you can. However, I think you need a panel to things like tabbing between controls.

When would I create more than one panel for a window?

when your controls have logical and/or visual groupings

If I do so, do they have any visible UI on any platform?

they can, depending on the style flags set, and things like background color.

I'm still reciting a lot of incantations without fully understanding what I'm doing. Any help gaining that deeper understanding would be greatly appreciated.

I hope that helped a bit.

The problem you had is very comon, and I think it stems from a lack of OO design. I try to make each Panel it's own class, then then add an instance of that class to the Frame or another panel, or....

In short, if you have names like:

self.A_Panel.A_control

or are doing things like:

Acontrol = wx.Something(self.Apanel, ...)

you'be got too mcuh nesting. Rather, you could do:

MyPanel(wx.Panel):
    def __init__(.....)
        ...
        ControlA = wx.something(self,...)
        ControlB = wx.something(self,...)

        S = wx.BoxSizer(...)

        S.Add(ControlA,....)
        S.Add(ControlB,....)
        S.Add(ControlC,....)
        self.SetSizer(S)

MyFrame(wx.Frame):
     def __init__(.....):
        ThePanel = MyPanel(self, ...)

This may help a bit:

wxPython Style Guide - wxPyWiki (see 7.)

-Chris

···

--
Christopher Barker, Ph.D.
Oceanographer

NOAA/OR&R/HAZMAT (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Joe,

<snip>

Why can't I set a sizer for the frame itself?

you can. However, I think you need a panel to things like tabbing between controls.

You also need the panel to make your program look "right" on Windows. Try leaving it out and you'll notice that the light gray background color goes away and you end up with a rather ugly dark gray. I usually have a sizer in my panel that controls the layout of my widgets in said panel. I think Robin said that he usually puts the panel in a sizer as well a couple of weeks ago on this list. So you have something like the following hierarchy:

Frame --> sizer --> Panel --> sizer --> widgets

I usually don't have that first sizer in my programs, but I remember thinking that that could be useful...

···

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

Blog: http://blog.pythonlibrary.org
Python Extension Building Network: http://www.pythonlibrary.org

Mike wrote:

Why can't I set a sizer for the frame itself?

you can. However, I think you need a panel to things like tabbing between controls.

You also need the panel to make your program look "right" on Windows.

good point -- I had forgotten about that:

you have something like the following hierarchy:

Frame --> sizer --> Panel --> sizer --> widgets

I usually don't have that first sizer in my programs, but I remember thinking that that could be useful...

If you only have the one Panel, it will fill the Frame, so that sizer isn't needed.

That is a more-or-less standard structure. My suggestion is that you don't put it all in your Frame class, but rather, create a Panel class, where most of your code goes.

Also, remember that there are three separate but somewhat parallel hierarchies in a wxPython GUI:

1) The wx.Window parent-child hierarchy
2) the Sizer hierarchy
3) The Python class-subclass hierachy

I try to keep these kin dof in-sync, so that each the Python class hierarchy follows the parent-child hierarchy -- I think if makes the code easier to maintain and re-use and less error prone.

-Chris

···

--
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

Mike wrote:

Joe,

<snip>

Why can't I set a sizer for the frame itself?

you can. However, I think you need a panel to things like tabbing between controls.

You also need the panel to make your program look "right" on Windows. Try leaving it out and you'll notice that the light gray background color goes away and you end up with a rather ugly dark gray. I usually have a sizer in my panel that controls the layout of my widgets in said panel. I think Robin said that he usually puts the panel in a sizer as well a couple of weeks ago on this list. So you have something like the following hierarchy:

Frame --> sizer --> Panel --> sizer --> widgets

I usually don't have that first sizer in my programs, but I remember thinking that that could be useful...

I do it because then if I do something like frame.Fit() then it will be using that top level sizer for the size calculation instead of the current size of the panel.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

That is a more-or-less standard structure. My suggestion is that you don't put it all in your Frame class, but rather, create a Panel class, where most of your code goes.

Yes, I'm just now starting to really "grok" the purpose of Panel (thanks to the kind help on this list). It's analogous to a ContainerControl in REALbasic (in case there are any other RB-heads who may read this).

Also, remember that there are three separate but somewhat parallel hierarchies in a wxPython GUI:

1) The wx.Window parent-child hierarchy
2) the Sizer hierarchy
3) The Python class-subclass hierachy

I've just started to grok that, too. It explains why you need to specify a parent when you create a wx.Window, but then also need to add it to a sizer. (It also explains why you can do away with the sizers entirely, if you want to position things yourself in the resize event... an approach which might make sense in some situations.)

Best,
- Joe

···

On Nov 18, 2008, at 10:16 AM, Christopher Barker wrote:

If you are just in starting-to-grok mode, maybe leaving sizers to the side for
a week or so might be a good idea, and you can just parent a lot of widgets
on panels. I found a visual way of placing helped to understand it, like using
Boa Constructor, which allows you to just drop panels and other widgets onto
a Designer frame and it generates the code (which you can then study).

But sizers are vital to looking good/consistent once you want to do anything
more involved or cross-platform, and ultimately they make it easier, too. One
way of thinking of this is: panels are rectangular containers of screen space,
sizers are rules of sizing (and so the names pretty much match what they are).

Che

···

On Tue, Nov 18, 2008 at 6:44 PM, Joe Strout <joe@strout.net> wrote:

On Nov 18, 2008, at 10:16 AM, Christopher Barker wrote:

That is a more-or-less standard structure. My suggestion is that you don't
put it all in your Frame class, but rather, create a Panel class, where most
of your code goes.

Yes, I'm just now starting to really "grok" the purpose of Panel (thanks to
the kind help on this list). It's analogous to a ContainerControl in
REALbasic (in case there are any other RB-heads who may read this).

Also, remember that there are three separate but somewhat parallel
hierarchies in a wxPython GUI:

1) The wx.Window parent-child hierarchy
2) the Sizer hierarchy
3) The Python class-subclass hierachy

I've just started to grok that, too. It explains why you need to specify a
parent when you create a wx.Window, but then also need to add it to a sizer.
(It also explains why you can do away with the sizers entirely, if you want
to position things yourself in the resize event... an approach which might
make sense in some situations.)