Search code examples
pythonuser-interfaceresizewxpythonboxsizer

Keeping Panels From Growing in wxPython


I'm attempting to arrange some panels in wxPython. A rough representation of the layout is here: Abstract example of the layout needed.

Essentially, I'm looking for a left and right panel, such that - when resized - the left (orange) panel (and its contents) is never resized, and the right (blue) panel can stretch/grow as much as necessary, but only horizontally.

The code I have thus far (with some random filler widgets) is below. My questions follow the code:

import wx
import wx.lib.scrolledpanel as scrolled

class MainWindow(wx.Frame):
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent)

        #add position panel
        posPnl = IdPanel(self)
        lbl1 = wx.StaticText(posPnl, label="Position")
        lbl2 = wx.StaticText(posPnl, label="Size")
        sizeCtrl = wx.TextCtrl(posPnl)

        posPnlSzr = wx.BoxSizer(wx.VERTICAL)
        posPnlSzr.Add(lbl1, 1, wx.FIXED&wx.LEFT)
        posPnlSzr.Add(sizeCtrl, 1, wx.LEFT&wx.FIXED)
        posPnlSzr.Add(lbl2, 1, wx.FIXED&wx.LEFT)

        posPnl.SetSizer(posPnlSzr)

        posPnl2 = TimelinePanel(self)
        lbl12 = wx.StaticText(posPnl2, label="Position")
        lbl22 = wx.StaticText(posPnl2, label="Size")
        sizeCtrl2 = wx.TextCtrl(posPnl2)

        posPnlSzr2 = wx.BoxSizer(wx.VERTICAL)
        posPnlSzr2.Add(lbl12, 1, wx.GROW)
        posPnlSzr2.Add(sizeCtrl2, 1, wx.GROW)
        posPnlSzr2.Add(lbl22, 1, wx.GROW)

        posPnl2.SetSizer(posPnlSzr2)

        mainSzr = wx.BoxSizer(wx.HORIZONTAL)
        mainSzr.Add(posPnl, 1, wx.FIXED)
        #mainSzr.AddSpacer(10)
        mainSzr.Add(posPnl2, 1, wx.GROW)

        self.SetSizerAndFit(mainSzr)
        self.Show()

class IdPanel(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent, -1, size = (400, 200))
        self.SetBackgroundColour((255, 0, 255))

class TimelinePanel(scrolled.ScrolledPanel):
    def __init__(self, parent):
        scrolled.ScrolledPanel.__init__(self, parent, -1, size = (300, 200))
        self.SetBackgroundColour((255, 0, 0))


app = wx.App(False)
frame = MainWindow(None, "Trading Client")
app.MainLoop()

My questions:

  1. How can I use sizers to ensure only the right panel expands, and only horizontally? Currently the contents of the left panel stay fixed, but the panel itself still expands.
  2. If I wanted to modify the first question slightly so that only the right expands horizontally, but both panels expand vertically, what would I need to do?
  3. I'm using a wx.lib.scrolledpanel for the x axis for the right panel, but I can't seem to contract the window horizontally at all to make it appear. I'm unsure if there's a setting about mix/max panel size, etc, that may help this?

Solution

  • 1: Use the proportion argument in sizer.Add when adding your two panels to the main sizer:

    mainSzr.Add(posPnl, 0)
    mainSzr.Add(posPnl2, 1)
    

    Proportion affects how that panel resizes in proportion to all the other sibling sizers (where 0 means don't resize). The flags wx.FIXED and wx.GROW are unrelated to your goal here.

    http://wxpython.org/docs/api/wx.Sizer-class.html#Add

    So for example, if you wanted both to increase, but the right to grow twice as fast as the left, you could use:

    mainSzr.Add(posPnl, 1)
    mainSzr.Add(posPnl2, 2)
    

    2: Use the wx.EXPAND flag to make something in a horizontal sizer expand to fill its vertical space (or vice versa for vertical sizer / horizontal space).

    mainSzr.Add(posPnl, 0, wx.EXPAND)
    mainSzr.Add(posPnl2, 1, wx.EXPAND)
    

    3: Add a self.SetupScrolling() to TimelinePanel's __init__ function, which is required for a scrolledpanel to operate. Then when the panel's content is big enough to require scrollbars, it'll be added.