Search code examples
pythonpython-3.xwxpython

How to correctly expand widgets in a wxPython dialog?


I an trying to get a minimal wxPython GUI working, but I failed so far in achieving the desired result. What I want is to expand the text input widget in the first line so that it fills up the width of the dialog/frame. I want the input box become as wide so that its right border aligns with the right border of the button in the (wider) second line.

Sample Screenshot

I thought that's what the wx.EXPAND flag is for when adding to the sizer, but apparently I am doing something wrong. Here is my code in a working example:

import wx

class MyApp(wx.Frame):
    def __init__(self):
        super(MyApp, self).__init__(None, title="wxPython Sizers", style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER)

        self.panel = wx.Panel(self)
        self.main_sizer = wx.BoxSizer(wx.VERTICAL)

        # First line, should expand it's width to fit the second line
        panel_sizer = wx.BoxSizer(wx.VERTICAL)
        hbox = wx.BoxSizer(wx.HORIZONTAL)
        text = wx.StaticText(self.panel, label="Short label:")
        hbox.Add(text, flag=wx.ALIGN_CENTER_VERTICAL)
        numtext = wx.TextCtrl(self.panel)
        hbox.Add(numtext, flag=wx.LEFT | wx.EXPAND, border=10)
        panel_sizer.Add(hbox)

        # The second, wider line
        hbox = wx.BoxSizer(wx.HORIZONTAL)
        text = wx.StaticText(self.panel, label="This is a long label:")
        hbox.Add(text, flag=wx.ALIGN_CENTER_VERTICAL)
        img_folder_button = wx.Button(self.panel, label="Button")
        hbox.Add(img_folder_button, flag=wx.LEFT, border=10)
        panel_sizer.Add(hbox, flag=wx.TOP, border=15)

        # We need only this one sizer for the panel
        self.panel.SetSizer(panel_sizer)

        # Set final dialog layout
        self.main_sizer.Add(self.panel, proportion=1, flag=wx.ALL | wx.EXPAND, border=15)
        self.SetSizer(self.main_sizer)
        self.Layout()
        self.Fit()
        self.Center()
        self.Show()

if __name__ == "__main__":
    wxapp = wx.App()
    myApp = MyApp()
    wxapp.MainLoop()

Solution

  • Be consistent with the use of proportion and border.
    Rather than re-use hbox declare them separately and expand the button as well in case the user the expands the frame.

    import wx
    
    class MyApp(wx.Frame):
        def __init__(self):
            super(MyApp, self).__init__(None, title="wxPython Sizers", style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER)
    
            self.panel = wx.Panel(self)
            self.main_sizer = wx.BoxSizer(wx.VERTICAL)
    
            # First line, should expand it's width to fit the second line
            panel_sizer = wx.BoxSizer(wx.VERTICAL)
            hbox1 = wx.BoxSizer(wx.HORIZONTAL)
            text = wx.StaticText(self.panel, label="Short label:")
            hbox1.Add(text, flag=wx.ALIGN_CENTER_VERTICAL)
            numtext = wx.TextCtrl(self.panel)
            hbox1.Add(numtext, proportion=1, flag=wx.LEFT | wx.EXPAND, border=15)
    
            # The second, wider line
            hbox2 = wx.BoxSizer(wx.HORIZONTAL)
            text = wx.StaticText(self.panel, label="This is a long label:")
            hbox2.Add(text, flag=wx.ALIGN_CENTER_VERTICAL)
            img_folder_button = wx.Button(self.panel, label="Button")
            hbox2.Add(img_folder_button, proportion=1, flag=wx.LEFT | wx.EXPAND, border=15)
            panel_sizer.Add(hbox1, flag=wx.TOP | wx.EXPAND, border=15)
            panel_sizer.Add(hbox2, flag=wx.TOP | wx.EXPAND, border=15)
    
            # We need only this one sizer for the panel
            self.panel.SetSizer(panel_sizer)
    
            # Set final dialog layout
            self.main_sizer.Add(self.panel, proportion=1, flag=wx.ALL | wx.EXPAND, border=15)
            self.SetSizerAndFit(self.main_sizer)
            self.Layout()
            self.Center()
            self.Show()
    
    if __name__ == "__main__":
        wxapp = wx.App()
        myApp = MyApp()
        wxapp.MainLoop()
    

    enter image description here enter image description here