Search code examples
pythonuser-interfacewxpythonboxsizer

wxPython -- BoxSizers not placing things correctly


I can't figure out what I'm doing wrong. I just made the jump from Tkinter to wxPython and I'm trying to figure out BoxSizers. I'd look this question up, but I don't even know what to look up. This panel is filling the space of a Frame, it's supposed to show a line of text with a progressbar underneath it and that's all supposed to take up the bottom 1/5 of the panel or so, centered horizontally (eventually I'm going to add a background image behind it). But what happens is I only see the text and only about 40% down from the top, aligned to the left edge of the window. Here's the code:

class KhPanel(wx.Panel):

def __init__(self, parent, configSet, selectWindow):
    wx.Panel.__init__(self, parent=parent)
    self.frame = parent
    self.configSet = configSet
    whichWindow = getattr(self, selectWindow)
    whichWindow()

def configWindow(self):
    gaugeWidth = (1/5)*self.configSet["width"]
    gaugeHeight = (1/10)*self.configSet["height"]
    gaugeMax = 100
    topBuffer = (8/10)*self.configSet["height"]
    itemSep = (1/16)*self.configSet["height"]

    vSizer = wx.BoxSizer(wx.VERTICAL)
    textSizer = wx.BoxSizer(wx.HORIZONTAL)
    progressSizer = wx.BoxSizer(wx.HORIZONTAL)

    configText = wx.StaticText(self, label="STUFF", style=wx.ALIGN_CENTER)
    configProgressBar = wx.Gauge(self, range=gaugeMax, size=(gaugeWidth, gaugeHeight))

    textSizer.Add(configText, 1, wx.ALIGN_CENTER, 0)
    progressSizer.Add(configProgressBar, 1, wx.ALIGN_CENTER, 1)
    vSizer.Add(textSizer, 1, wx.TOP, topBuffer)
    vSizer.Add(progressSizer, 1, wx.TOP, itemSep)

    self.SetSizer(vSizer)
    vSizer.Fit(self)
    return

If you need the info, configSet.width and height are the width and height of the parent window (currently 340 x 270). And selectWindow, in this case, is "configWindow"


Solution

  • Running this code, the gaugeWidth and gaugeHeight are both getting set to zero, which is why the progressbar is not showing. This is due to the fact that you are doing integer math here, so 1 divided by 5 is 0. Same with 1/10. Just change those lines to:

    gaugeWidth = (1/5.0)*self.configSet["width"]
    gaugeHeight = (1/10.0)*self.configSet["height"]
    

    Then the gauge will appear. Here's some fully runnable code, slightly modified from your unrunnable original:

    import wx
    
    class KhPanel(wx.Panel):
    
        def __init__(self, parent, configSet):
            wx.Panel.__init__(self, parent=parent)
            self.frame = parent
            self.configSet = configSet
            self.configWindow()
    
    
        def configWindow(self):
            gaugeWidth = (1/5.0)*self.configSet["width"]
            gaugeHeight = (1/10.0)*self.configSet["height"]
            gaugeMax = 100
            topBuffer = (8/10)*self.configSet["height"]
            itemSep = (1/16)*self.configSet["height"]
    
            vSizer = wx.BoxSizer(wx.VERTICAL)
            textSizer = wx.BoxSizer(wx.HORIZONTAL)
            progressSizer = wx.BoxSizer(wx.HORIZONTAL)
    
            configText = wx.StaticText(self, label="STUFF", style=wx.ALIGN_CENTER)
            configProgressBar = wx.Gauge(self, range=gaugeMax, size=(gaugeWidth, gaugeHeight))
    
            textSizer.Add(configText, 1, wx.ALIGN_CENTER, 0)
            progressSizer.Add(configProgressBar, 1, wx.ALIGN_CENTER, 1)
            vSizer.Add(textSizer, 1, wx.TOP, topBuffer)
            vSizer.Add(progressSizer, 1, wx.TOP, itemSep)
    
            self.SetSizer(vSizer)
            vSizer.Fit(self)
    
    class MyFrame(wx.Frame):
    
        def __init__(self):
            wx.Frame.__init__(self, None, title="Test")
            config = {'width':340, 'height':270}
            panel = KhPanel(self, config)
    
            self.Show()
    
    if __name__ == "__main__":
        app = wx.App()
        frame = MyFrame()
        app.MainLoop()