Sanity Check: wx.GridBagSizer
19 answers - 3186 bytes -

I've used Boa Constructor's Designer to add widgets to a wx.Panel that will
eventually be on a wx.Notebook page. However, after getting totally lost
trying to use sizers in BC, I decided to add them manually.
Here in modModel,py I have initiated a wx.Panel and widgets:
class modModel(wx.Panel):
def _init_ctrls(self, prnt):
# generated method, don't edit
wx.Panelinit__(self, id=wxID_MDMDEL, name='modModel', parent=prnt,
pos=wx.Point(382, 318), size=wx.Size(700, 500),
style=wx.TAB_TRAVERSAL)
self.SetToolTipString('Model information')
self.SetClientSize(wx.Size(700, 500))
self.modNameLab = wx.StaticText(id=wxID_MDMDELMDNAMELAB,
label='Model name: ', name='modNameLab', parent=self, pos=wx.Point(5,
10), size=wx.Size(87, 17), style=0)
('')
self.modNameTxt = wx.TextCtrl(id=wxID_MDMDELMDNAMETXT, name='modNameTxt',
parent=self, pos=wx.Point(95, 10), size=wx.Size(200, 25),
style=wx.TE_LEFT | wx.TAB_TRAVERSAL | wx.RAISED_BRDER, value='')
(wx.Size(200, 25))
('Model name.')
self.modNameTxt.Bind(wx.EVT_TEXT_ENTER, NameTxtTextEnter,
id=wxID_MDMDELMDNAMETXT)
self.modNameTxt.Bind(wx.EVT_TEXT, NameTxtText,
id=wxID_MDMDELMDNAMETXT)
self.modNameTxt.Bind(wx.EVT_LEFT_UP, ModNameTxtLeftUp)
self.modDescLab = wx.StaticText(id=wxID_MDMDELMDDESCLAB,
label='Model description: ', name='modDescLab', parent=self,
pos=wx.Point(310, 10), size=wx.Size(120, 17), style=0)
('Model description')
self.modDescTxt = wx.TextCtrl(id=wxID_MDMDELMDDESCTXT, name='modDescTxt',
parent=self, pos=wx.Point(430, 10), size=wx.Size(240, 70),
style=wx.TAB_TRAVERSAL | wx.TE_MULTILINE | wx.TE_LINEWRAP | wx.RAISED_BRDER | wx.HSCRLL,
value='')
self.modDescTxt.Bind(wx.EVT_TEXT_ENTER, ModDescTxtTextEnter,
id=wxID_MDMDELMDDESCTXT)
self.modDescTxt.Bind(wx.EVT_TEXT, ModDescTxtText,
id=wxID_MDMDELMDDESCTXT)
self.modDescTxt.Bind(wx.EVT_LEFT_UP, ModDescTxtLeftUp)
There are other widgets, of course, but these two come at the top of the
panel.
Then I looked at the GrabBagSizer.py demo in the 2.6.1.0 demo directory and
tried to match the constructor syntax in the demo with what I see in the new
API doc and the older wxWidgets class list and with what I BC produced for
the wx.StaticText and wx.TextCtrl widgets above. After a lot of pondering, I
came up with this:
def _init_sizers(self):
gbs = self.gbs = wx.GrabBagSizer(hgap=5,vgap=5)
gbs.Add(self, modNameLab, (0,0))
gbs.Add(self, modNameTxt, (0,1), (0,2))
gbs.Add(self, modDescLab, (0,3))
gbs.Add(self, modDescTxt, (0,4), (1,3))
I suspect that the size and positioning needs to come out of the widget
constructors, and I need to learn how to place those widgets within the
GrabBagSizer. The docs available to me have been consulted, but I see more
discrepancies than uniformity. A nudge in the right direction would be
greatly appreciated.
TIA,
Rich
No.1 | | 1524 bytes |
| 
Thursday, November 17, 2005, 4:32:23 PM, Rich Shepard wrote:
[snip]
Then I looked at the GrabBagSizer.py demo in the 2.6.1.0 demo
directory and tried to match the constructor syntax in the demo with
what I see in the new API doc and the older wxWidgets class list and
with what I BC produced for the wx.StaticText and wx.TextCtrl
widgets above. After a lot of pondering, I came up with this:
def _init_sizers(self):
gbs = self.gbs = wx.GrabBagSizer(hgap=5,vgap=5)
Do you mean GridBagSizer? If you do, you can just call a
gbs = self.gbs = wx.GridBagSizer(5, 5)
but remember the order of the arguments is vgap, hgap.
gbs.Add(self, modNameLab, (0,0))
gbs.Add(self, modNameTxt, (0,1), (0,2))
gbs.Add(self, modDescLab, (0,3))
gbs.Add(self, modDescTxt, (0,4), (1,3))
wxPython is wondering why are you trying to put 'self' 4 times inside
the same sizer
According to the docs, the GridBagSizer.Add method suports the
following arguments, and the lines above don't match any of them:
Add(window, pos, span, flag, border, userData)
Add(sizer, pos, span, flag, border, userData)
Add(width, height, pos, span, flag, border, userData)
Add(item)
-- tacao
No bits were harmed during the making of this e-mail.
To unsubscribe, e-mail: wxPython-users-unsubscribe (AT) lists (DOT) wxwidgets.org
For additional commands, e-mail: wxPython-users-help (AT) lists (DOT) wxwidgets.org
No.2 | | 1098 bytes |
| 
Thu, 17 Nov 2005, E. A. Tacao wrote:
Do you mean GridBagSizer? If you do, you can just call a
Yes. That was a typo and since corrected.
gbs = self.gbs = wx.GridBagSizer(5, 5)
wxPython is wondering why are you trying to put 'self' 4 times inside
the same sizer
According to the docs, the GridBagSizer.Add method suports the following
arguments, and the lines above don't match any of them:
Add(window, pos, span, flag, border, userData)
Add(sizer, pos, span, flag, border, userData)
Add(width, height, pos, span, flag, border, userData)
Add(item)
What I'm trying to correlate is the description of the widget generated by
Boa with one of the constructors. The API doc shows two constructors:
Add(self, item, pos, span, flag, border, userData) Adds an item to the
sizer at the grid cell pos, optionally spanning more than one row or
column as specified with span.
AddItem(*args, **kwargs) Add(self, GBSizerItem item) -wx.GBSizerItem
and I was trying to apply the first.
Rich
No.3 | | 1172 bytes |
| 
Thu, 17 Nov 2005, E. A. Tacao wrote:
According to the docs, the GridBagSizer.Add method suports the following
arguments, and the lines above don't match any of them:
Add(window, pos, span, flag, border, userData)
Add(sizer, pos, span, flag, border, userData)
Add(width, height, pos, span, flag, border, userData)
Add(item)
tacao,
I've made a bunch of changes, but it will still not run without errors.
What would be most helpful to me would be seeing how my code needs to be
altered to put the widgets in a wx.GridBagSizer. I can make a tarball (or zip
file) of the source modules if that would help.
Perhaps part of the problem is the way Boa is generating the code for the
wx.Panel and the widgets placed on there. I have having difficulties
reconciling that code with the wx.GridBagSizer constructors in the docs. If
it would be better for me to write in a text editor (emacs is my choice),
then I'll do that. However, right now I just don't see how to fix the errors
reported in the traceback.
A little hand-holding will go a long way. :-)
Thanks,
Rich
No.4 | | 435 bytes |
| 
Rich Shepard wrote:
A little hand-holding will go a long way. :-)
I don't know if it's what you need, but check out
and look at Section 3.3.
Hope this helps a bit,
Don Dwiggins
Advanced Publishing Technology
To unsubscribe, e-mail: wxPython-users-unsubscribe (AT) lists (DOT) wxwidgets.org
For additional commands, e-mail: wxPython-users-help (AT) lists (DOT) wxwidgets.org
No.5 | | 464 bytes |
| 
Thu, 17 Nov 2005, Don Dwiggins wrote:
I don't know if it's what you need, but check out
and look at Section 3.3.
Don,
I'll go over this again. Thank you for the reminder.
My reference to the hand holding is how the Boa output needs to be modified
so I can put the widgets in the GridBagSizer. Rather than starting the whole
project from scratch I'd like to learn how to modify the Boa output.
Rich
No.6 | | 1668 bytes |
| 
Thu, 17 Nov 2005, E. A. Tacao wrote:
Do you mean GridBagSizer? If you do, you can just call a
gbs = self.gbs = wx.GridBagSizer(5, 5)
>gbs.Add(self, modNameLab, (0,0))
wxPython is wondering why are you trying to put 'self' 4 times inside
the same sizer
Through trial and error (as well as a lot of reading of the docs), I've
gotten somewhat closer I think. Here's how the class begins:
class modModel(wx.Panel):
def _init_ctrls(self, prnt):
gbs = self.gbs = wx.GridBagSizer(5,5)
# generated method, don't edit
wx.Panelinit__(self, id=wxID_MDMDEL, name='modModel', parent=prnt,
pos=wx.Point(382, 318), size=wx.Size(700, 500), style=wx.TAB_TRAVERSAL)
self.SetToolTipString('Model information')
self.SetClientSize(wx.Size(700, 500))
Then I define the widgets. Below that I have:
gbs.Add(self, wxID_MDMDELMDNAMELAB, (0,0), wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
gbs.Add(self, wxID_MDMDELMDNAMETXT, (0,1), (0,2), wx.ALL, 5)
gbs.Add(self, wxID_MDMDELMDDESCLAB, (0,3), wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
gbs.Add(self, wxID_MDMDELMDDESCTXT, (0,4), (1,3), wx.ALL, 5)
Without the 'self' I get all sorts of errors. Now, the error message is a
python error:
File "/", line 139, in __init__
gbs.Add(self, wxID_MDMDELMDNAMELAB, (0,0), wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
NameError: global name 'gbs' is not defined
I thought that gbs was local; obviously python disagrees. How should I
define gbs in this context?
Thanks,
Rich
No.7 | | 1544 bytes |
| 
Rich Shepard wrote:
class modModel(wx.Panel):
def _init_ctrls(self, prnt):
gbs = self.gbs = wx.GridBagSizer(5,5)
# generated method, don't edit
wx.Panelinit__(self, id=wxID_MDMDEL, name='modModel', parent=prnt,
pos=wx.Point(382, 318), size=wx.Size(700, 500),
style=wx.TAB_TRAVERSAL)
self.SetToolTipString('Model information')
self.SetClientSize(wx.Size(700, 500))
Then I define the widgets. Below that I have:
gbs.Add(self, wxID_MDMDELMDNAMELAB, (0,0),
wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
gbs.Add(self, wxID_MDMDELMDNAMETXT, (0,1), (0,2), wx.ALL, 5)
gbs.Add(self, wxID_MDMDELMDDESCLAB, (0,3),
wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
gbs.Add(self, wxID_MDMDELMDDESCTXT, (0,4), (1,3), wx.ALL, 5)
Without the 'self' I get all sorts of errors. Now, the error message is a
But you really don't want to add self to the sizer!
This is what you want:
Add(window, pos, span, flag, border, userData)
no self, no ID, I think you want:
gbs.Add(self.modNameLabel, (0,1), (0,2), wx.ALL, 5)
As I've mentioned on another thread, you rarely need to use explicit IDs.
However, you really need to put this in a small, self contained,
complete application, then we can test any changes we suggest.
also, even though You'd like to make use of the Boa-generated code, it
might be easier top make a complete GridBagSizer example by hand first,
to make sure you understand it.
-Chris
No.8 | | 1370 bytes |
| 
Thu, 17 Nov 2005, Chris Barker wrote:
But you really don't want to add self to the sizer!
Chris,
I know, but I had been floundering around (yes, thrashing on the bottom).
This is what you want:
Add(window, pos, span, flag, border, userData)
I see this, but defining the window is where I was hung up.
no self, no ID, I think you want:
gbs.Add(self.modNameLabel, (0,1), (0,2), wx.ALL, 5)
^^^^^^^^^^^^^^^^^
That's one I didn't try.
As I've mentioned on another thread, you rarely need to use explicit IDs.
Yeah, it's what Boa adds.
However, you really need to put this in a small, self contained, complete
application, then we can test any changes we suggest.
also, even though You'd like to make use of the Boa-generated code, it
might be easier top make a complete GridBagSizer example by hand first, to
make sure you understand it.
I just came back from walking the dogs and, during the walk, I decided
that's exactly what I need. Start with a stand-alone GridBagSizer in a frame
using the widgets I want. Then change the frame to a panel, and work my way
up to where I need to be. And, all this is my favorite text editor rather
than in an IDE.
Many thanks -- progress report tomorrow,
Rich
No.9 | | 235 bytes |
| 
Chris Barker wrote:
However, you really need to put this in a small, self contained,
complete application, then we can test any changes we suggest.
I couldn't help myself, here's something to play with:
-Chris
No.10 | | 924 bytes |
| 
Thursday, November 17, 2005, 10:11:31 PM, Chris Barker wrote:
Thursday, November 17, 2005, 10:09:54 PM, Rich Shepard wrote:
>Thu, 17 Nov 2005, Chris Barker wrote:
>>
>This is what you want:
>>
>Add(window, pos, span, flag, border, userData)
I see this, but defining the window is where I was hung up.
I'm sorry I didn't mentioned it earlier: 'window' is the thing you
want to put inside the sizer.
I couldn't help myself, here's something to play with:
That's a nice one.
-- tacao
No bits were harmed during the making of this e-mail.
To unsubscribe, e-mail: wxPython-users-unsubscribe (AT) lists (DOT) wxwidgets.org
For additional commands, e-mail: wxPython-users-help (AT) lists (DOT) wxwidgets.org
No.11 | | 827 bytes |
| 
Thu, 17 Nov 2005, Chris Barker wrote:
Chris Barker wrote:
>However, you really need to put this in a small, self contained, complete
>application, then we can test any changes we suggest.
>
I couldn't help myself, here's something to play with:
Chris,
I modified the code from the wiki and made it run. Now I'd like to
understand:
1.) Why the wx.Frame is not the size specified in the __init
2.) How to space the widgets more appropriately; that is, have the
wx.TextCtrls nearer the wx.StaticTexts.
3.) Why, when I change the span tuple to increase the number of rows, the
position is changed instead.
Perhaps I really need a wx.FlexGridSizer instead of the wx.GridBagSizer.
Thanks,
Rich
No.12 | | 475 bytes |
| 
Fri, 18 Nov 2005, E. A. Tacao wrote:
I'm sorry I didn't mentioned it earlier: 'window' is the thing you
want to put inside the sizer.
'Window' as an attribute of the wx.GridBagSizer I thought was where the
widget was addded.
When I get this module displaying properly, it should fit in the sequence:
wx.Frame -wx.Panel -wx.Notebook -wx.Panel -module with sizers and
widgets. No?
Thanks,
Rich
No.13 | | 1109 bytes |
| 
This thread finally triggered a vague memory, and I was able to track it
down. Here's an excerpt from a presentation called "Cross Platform
Desktop Applications with Python" by Nathan R. Yergler
():
Don't use GridBagSizer. Ever.
The GridBagSizer is a tempting widget, since it allows lots of
flexibility in organizing widgets into columns/rows, and also supports
spanning rows and columns. However, my experience has been that it has
layout problems on S X, especially when nested within another sizer.
Therefore, it's often easier to use nested FlexGridSizers to
accomplish the same task.
For more detail, or to argue with him ;^), check the contact info at
http://www.yergler.net/. Maybe he could be lured to this thread to
discuss his experiences. (I note that he seems to be mostly oriented to
S-X.)
Don Dwiggins
Advanced Publishing Technology
To unsubscribe, e-mail: wxPython-users-unsubscribe (AT) lists (DOT) wxwidgets.org
For additional commands, e-mail: wxPython-users-help (AT) lists (DOT) wxwidgets.org
No.14 | | 1590 bytes |
| 
Friday, November 18, 2005, 1:05:46 AM, Don Dwiggins wrote:
This thread finally triggered a vague memory, and I was able to
track it down. Here's an excerpt from a presentation called "Cross
Platform Desktop Applications with Python" by Nathan R. Yergler
():
>Don't use GridBagSizer. Ever. The GridBagSizer is a tempting
>widget, since it allows lots of flexibility in organizing widgets
>into columns/rows, and also supports spanning rows and columns.
>However, my experience has been that it has layout problems on S
>X, especially when nested within another sizer. Therefore, it's
>often easier to use nested FlexGridSizers to accomplish the same
>task.
For more detail, or to argue with him ;^), check the contact info at
http://www.yergler.net/. Maybe he could be lured to this thread to
discuss his experiences. (I note that he seems to be mostly oriented
to S-X.)
If you are building some complex layout use GridBagSizer. Always.
If you find layout problems on S X, please submit bug reports under
the "S X specific" cathegory. 8^)
one would find himself subclassing a PySizer class only to
eventually mimic a GridBagSizer's behavior
But perhaps I'm wrong. 8^)
-- tacao
No bits were harmed during the making of this e-mail.
To unsubscribe, e-mail: wxPython-users-unsubscribe (AT) lists (DOT) wxwidgets.org
For additional commands, e-mail: wxPython-users-help (AT) lists (DOT) wxwidgets.org
No.15 | | 577 bytes |
| 
Friday, November 18, 2005, 12:14:02 AM, Rich Shepard wrote:
When I get this module displaying properly, it should fit in the
sequence:
wx.Frame -wx.Panel -wx.Notebook -wx.Panel -module with
sizers and widgets. No?
Yes, if 'module' is the only thing you are to put in the wx.Panel.
-- tacao
No bits were harmed during the making of this e-mail.
To unsubscribe, e-mail: wxPython-users-unsubscribe (AT) lists (DOT) wxwidgets.org
For additional commands, e-mail: wxPython-users-help (AT) lists (DOT) wxwidgets.org
No.16 | | 376 bytes |
| 
Fri, 18 Nov 2005, E. A. Tacao wrote:
If you are building some complex layout use GridBagSizer. Always.
My test application showed me that the layout with a GridBagSizer was not
what I wanted. For example, the horizontal span of the wx.RadioBox stretched
the left-most column so the static text and text control above it were too
far apart.
Rich
No.17 | | 2404 bytes |
| 
Rich Shepard wrote:
My test application showed me that the layout with a GridBagSizer was not
what I wanted.
If you don't want rows and columns, use Box Sizers. If you do;
If you want the rows and columns all the same size, use a GridSizer
If you want the rows and columns to be able to be different sizes, use a
FlexGridSizer.
If you want items to be able to span more than one column or row, use a
GridBagSizer.
Principle of least complexity applies here.
What I'm now doing is working on learning wxPython by modifying a module
for my application that was originally generated by Boa.
Well, the coding style of auto-generated code is not likely to match mine!
I better understand what I'm doing, I'll want the UI to be based
on a
tabbed notebook. My current knowledge is that the sequence should be:
wx.Frame -wx.Panel -wx.Notebook -wx.Panel (on each page) -sizers
and
widgets. Is this still valid?
If the only thing on the Frame is the Notebook, then you probably don't
need the Panel.
Each Panel that will be put on the Notebook will be it's own custom
class, or an instance of a custom class, depending on how different each
page is.
The Widgets should be put on the panels, and laid out with Sizers. Look
for groups of widgets that work together, particularly groups that are
similar in multiple places, and make custom classes for these.
I'm still not clear on when a panel is preferred to a frame, or used in
addition to a frame.
They are different. A Frame is a top level window: one that does not
have e a parent. A wx.Window is the very minimalist window, with no
little functionality of it's own, that is used as the base class for all
other Windows (controls, etc). a wx.Panel is a wx.Window with some
additional functionality that make it easier to put multiple controls on
it, such as tab traversal. So a Panel is almost always used to hold a
collection of two or more controls.
I do hope the wxPython book is out soon and answers questions such as
this!
the answers are out there, but it is a lot harder to find them than it
would be in a book. You might want to consider the C++ wxWidgets book.
It's pretty good, and most of these issues are the same.
-Chris
No.18 | | 689 bytes |
| 
Fri, 18 Nov 2005, Chris Barker wrote:
the answers are out there, but it is a lot harder to find them than it
would be in a book. You might want to consider the C++ wxWidgets book. It's
pretty good, and most of these issues are the same.
Chris,
I'll probably go to Powell's tomorrow and buy a copy of the C++ book, just
for the general information.
I almost have a test running; there's a problem with the wx.Frame init at
line 165 (when the app is called). Naturally, I don't know where the error
really is. I've attached the code with the request that someone show me how
to fix it.
Thanks,
Rich
No.19 | | 670 bytes |
| 
Friday, November 18, 2005, 9:28:25 PM, Rich Shepard wrote:
there's a problem with the wx.Frame init at line 165 (when the app
is called). Naturally, I don't know where the error really is. I've
attached the code with the request that someone show me how to fix
it.
There are 2 __init__ methods, and python is trying to run the second
(at line #117), which needs 7 args.
-- tacao
No bits were harmed during the making of this e-mail.
To unsubscribe, e-mail: wxPython-users-unsubscribe (AT) lists (DOT) wxwidgets.org
For additional commands, e-mail: wxPython-users-help (AT) lists (DOT) wxwidgets.org