wxpythonwxwidgetssizer

Appropriate wx.Sizer(s) for the job?


I have a space in which I would like certain elements (represented here by A, B, D, and G) to each be in its own "corner" of the design. The corners ought to line up as if each of the four elements was repelling the other; a rectangle. This is to be contained within an unresizable panel. I will have several similar panels and want to keep the location of the elements as identical as possible. (I needed something a little more complex than a wx.Wizard, but with the same general idea.)

AAAAAAAAAA      BB


CCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCC
CCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCC


DDD EEE FFF    GGG

A represents a text in a large font.

B represents a numeric progress meter (e.g. "1 of 7") in a small font.

C represents a large block of text.

D, E, F, and G are buttons.

The G button is separated from others for functionality.

I have attempted nested wx.BoxSizers (horizontal boxes inside of one vertical box) without luck. My first problem with wx.BoxSizer is that the .SetMinSize on my last row has not been honored. The second problem is that I have no idea how to make the G button "take up space" without growing comically large, or how I can jam it up against the right edge and bottom edge.

I have tried to use a wx.GridBagSizer, but ran into entirely different issues.

After plowing through the various online tutorials and wxPython in Action, I'm a little frustrated. The relevant forums appear to see activity once every two weeks. "Playing around with it" has gotten me nowhere; I feel as if I am trying to smooth out a hump in ill-laid carpet.


Solution

  • Using BoxSizers and some flags like wx.EXPAND and wx.ALIGN_RIGHT, etc, you can get what you want. Here's an example

    import wx
    import string
    AF = string.ascii_uppercase[:7]
    
    class MyFrame(wx.Frame):
    
        def __init__(self):
            wx.Frame.__init__(self, None, size=(300,300))
    
            a, b, c, d, e, f, g = [wx.Button(self, -1, 4*c) for c in AF]
            a.SetMaxSize((200,100))   # 'a' won't get bigger than 200 wide
    
            # build the top row (with sizers I usually work from inside to out)
            hs0 = wx.BoxSizer(wx.HORIZONTAL)
            hs0.Add(a, 1, wx.ALIGN_LEFT)  # 1 here means expand with weight 1
            hs0.Add((0,0), 1)  # also expand the spacing
            hs0.Add(b, 0, wx.ALIGN_RIGHT)  # 0 means don't expand this
    
            # build the bottom row
            hs1 = wx.BoxSizer(wx.HORIZONTAL)
            hs1.Add(d, 0, wx.ALIGN_LEFT)
            hs1.Add((10,10), 0)
            hs1.Add(e, 0)
            hs1.Add((10,10), 0)
            hs1.Add(f, 0)
            hs1.Add((10, 10), 1)
            hs1.Add(g, 0, wx.ALIGN_RIGHT)
    
            # stack the rows vertically
            vs = wx.BoxSizer(wx.VERTICAL)
            vs.Add(hs0, flag=wx.EXPAND)   # expand in the orthogonal direction to sizer (here horizontal)
            vs.Add(c, 1, flag=wx.EXPAND)  
            vs.Add(hs1, flag=wx.EXPAND)
            self.SetSizer(vs)
    
    app = wx.PySimpleApp()
    frame = MyFrame()
    frame.Show(1)
    app.MainLoop()
    

    alt text