tags:

views:

536

answers:

2

I'm having trouble figuring out how to get the sizers in wxPython to work the way I want them to (aside: am I the only one who thinks that wxPython is poorly documented?). I've got 4 buttons and a textctrl that I want arranged like so:

==============================================
|WINDOW TITLE                          _ [] X|
|============================================|
|Button1  |  Button2  |   Button3  |  Button4|
|--------------------------------------------|
|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx|
|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx|
|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx|
|xxxxxxxxxxxxxxxxxxTextCtrlxxxxxxxxxxxxxxxxxx|
|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx|
|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx|
|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx|
==============================================

The buttons should expand horizontally, but not vertically, and the textctrl should expand both horizontally and vertically. I've tried pretty much every sizer listed in the wxPython demo program and none of them worked - multiple boxsizers, gridsizers + boxsizeres, plain gridsizer, flexgridsizer and rowcolsizer but none of it works, could someone help? For reference, here's the code that I've got right now.

            ...snip...
            panel = wx.Panel(self, -1)
            select_file = wx.Button(panel, self.BUTTON_0, "Select File")
            button1 = wx.Button(panel, self.BUTTON_1, "250 Words") 
            button2 = wx.Button(panel, self.BUTTON_2, "500 Words") 
            button3 = wx.Button(panel, self.BUTTON_3, "750 Words") 
            self.txt = wx.TextCtrl(panel, -1, "", style=wx.TE_MULTILINE | wx.TE_READONLY)

            # Now to re-do this with gridsizers instead.
            # 4 rows, 4 columns, 2 pixel gap horizontally and vertically.
            grid = rcs.RowColSizer()

            # These buttons need to expand to fill their space, and then
            # expand when the windows are resized.
            grid.Add( select_file, row=1, col=1 )
            grid.Add( button1, row=1, col=2 )
            grid.Add( button2, row=1, col=3 )
            grid.Add( button3, row=1, col=4 )
            grid.Add( self.txt, row=2, col=1 )
            ...snip...
+3  A: 

It took me a while to figure this out. It's something that I do with wxPython all the time. Essentially you need to nest box sizers. You need one vertical box sizer that holds two horizontal box sizers.

Here is the code you need:

import wx

class sizertest(wx.Panel):

    def __init__(self,parent):
        wx.Panel.__init__(self,parent)
        vsizer = wx.BoxSizer(wx.VERTICAL)
        hsizer1 = wx.BoxSizer(wx.HORIZONTAL)

        button1 = wx.Button(self,-1,"button 1")
        self.Bind( wx.EVT_BUTTON,self.button1,button1)
        hsizer1.Add(button1,1,wx.EXPAND)

        button2 = wx.Button(self,-1,"button 2")
        self.Bind( wx.EVT_BUTTON,self.button2,button2)
        hsizer1.Add(button2,1,wx.EXPAND)

        vsizer.Add(hsizer1,.1,wx.EXPAND)
        self.SetSizer(vsizer)

        tc = wx.TextCtrl(self,-1,"",style=wx.TE_MULTILINE)
        hsizer2 = wx.BoxSizer(wx.HORIZONTAL)
        hsizer2.Add(tc,1,wx.EXPAND)
        vsizer.Add(hsizer2,1,wx.EXPAND)

    def button1(self,event):pass
    def button2(self,event):pass


if __name__ == "__main__":
    app = wx.App()
    frame = wx.Frame(parent=None, id=-1, title="sizer test")
    panel = sizertest(frame)

    frame.Show()
    app.MainLoop()

The vertical sizer vsizer holds two horizontal sizers. The first horizontal sizer holds as many buttons as you want to add to it, and they can expand horizontally. Because you add it to the vertical sizer with a number less than one for its "weight" it will not expand vertically. The second horizontal sizer holds the text control, and it can expand to take up all the remaining horizontal and vertical space. Both sizers expand as the window is expanded.

I recommend that you get the book wxPython in Action by Rappin and Dunn - it really helped me understand how the wxPython sizers and screen layout works.

I use nested boxsizers for 99% of my wxPython programs.

Curt

Curt
Yep, nested box sizers are my general approach too.
FogleBird
+1 I mainly use (nested) boxsizers and flexgridsizers. And yes, it is a universal truth that wxpython is very poorly documented. I recommend the mailing list, just follow that for a few weeks and you'll be up to speed.
DrBloodmoney
A: 

There is a good deal of information on the wiki, check http://wiki.wxpython.org/UsingSizers for example. The image at the bottom is great at showing how all the flags and function arguments work.

Other good examples are -zetcodeand don't forget to check the wxwidgets pages too.

The samples/demo apps are great too available from the wxpython download page. I can't provide more than one link due to being a new StackOverflow user.

After a while of playing with sizers, they should hopefully "tick" - I find using them makes creating my GUIs a breeze.

Steven Sproat