wxPython 小部件是一个在另一个之上

wxPython widgets are one on top of the other

我正在构建一个 wxpython GUI。

当我 运行 代码时,所有组件都在左上角,彼此重叠。 当我调整 window 大小时,它们按计划对齐。

The window before resize

The window after resize

我该如何解决这个问题?

我的代码:

class Screen(wx.Frame):
def __init__(self, parent, title):
    wx.Frame.__init__(self, parent, title=title, size=(900,500))

    self.SetBackgroundColour("#E4F1FE")
    self.Show(True)

    self.InitUI()

def InitUI(self):

    pnlMain = wx.Panel(self, size=(900,500))

    # Setup Font
    font = wx.SystemSettings_GetFont(wx.SYS_SYSTEM_FONT)
    font.SetPointSize(9)

    # Setup horizontal box sizer
    self.bsMain = wx.BoxSizer(wx.HORIZONTAL)
    self.bsMain.SetDimension(0,0,900,500)

    # Setup LEFT box sizer
    self.bsLeft = wx.BoxSizer(wx.VERTICAL)
    self.bsLeft.SetMinSize((3*(self.GetSize()[0]/4),self.GetSize()[1]))

    # Make add button
    btnAdd = wx.Button(pnlMain, label="+", size=(50,50))

    # Add all the components to the LEFT sizer
    self.bsLeft.Add(btnAdd, flag = wx.ALIGN_BOTTOM | wx.ALIGN_LEFT )

    # Setup RIGHT bsMain sizer
    self.bsRight = wx.BoxSizer(wx.VERTICAL)
    self.bsRight.SetMinSize((self.GetSize()[0]/4,self.GetSize()[1]))

    # Make users headline
    stUsers = wx.StaticText(pnlMain, label="USERS")
    stUsers.SetFont(font)

    # Make users list control
    lcUsers = wx.ListCtrl(pnlMain,style=wx.LC_REPORT|wx.SUNKEN_BORDER)
    lcUsers.Show(True)
    lcUsers.InsertColumn(0,"user")
    lcUsers.InsertColumn(1,"status")

    # Add all the components to the RIGHT sizer
    self.bsRight.Add((-1,10))
    self.bsRight.Add(stUsers, flag=wx.LEFT | wx.EXPAND | wx.ALIGN_CENTER | wx.ALIGN_CENTRE, border=5)
    self.bsRight.Add((-1,10))
    self.bsRight.Add(lcUsers, flag=wx.EXPAND)


    # Add the vertical sizers to the horizontal sizer
    self.bsMain.Add(self.bsLeft)
    self.bsMain.Add(self.bsRight)

    # Add the vertical sizer to the panel
    pnlMain.SetSizer(self.bsMain)

这是新wxPython 程序员的常见问题。解决方案几乎总是调用顶级 sizer 的 Layout 方法。有时您需要改为调用顶级父级的 Layout。在您的情况下,两者都可以。您可以添加:

pnlMain.Layout()

self.bsMain.Layout()

InitUI 方法的底部,它应该会强制您的小部件在正确的位置重绘。我已经看到一些小部件表现不佳,因为它们在显示之前以零大小开始。在那些情况下,我通常需要使用 wx.CallAfter 来调用 Layout。无论如何,这是一个使用您的代码的完整示例:

import wx

class Screen(wx.Frame):
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, title=title, size=(900,500))

        self.SetBackgroundColour("#E4F1FE")
        self.Show(True)

        self.InitUI()

    def InitUI(self):

        pnlMain = wx.Panel(self, size=(900,500))

        # Setup Font
        font = wx.SystemSettings_GetFont(wx.SYS_SYSTEM_FONT)
        font.SetPointSize(9)

        # Setup horizontal box sizer
        self.bsMain = wx.BoxSizer(wx.HORIZONTAL)
        self.bsMain.SetDimension(0,0,900,500)

        # Setup LEFT box sizer
        self.bsLeft = wx.BoxSizer(wx.VERTICAL)
        self.bsLeft.SetMinSize((3*(self.GetSize()[0]/4),self.GetSize()[1]))

        # Make add button
        btnAdd = wx.Button(pnlMain, label="+", size=(50,50))

        # Add all the components to the LEFT sizer
        self.bsLeft.Add(btnAdd, flag = wx.ALIGN_BOTTOM | wx.ALIGN_LEFT )

        # Setup RIGHT bsMain sizer
        self.bsRight = wx.BoxSizer(wx.VERTICAL)
        self.bsRight.SetMinSize((self.GetSize()[0]/4,self.GetSize()[1]))

        # Make users headline
        stUsers = wx.StaticText(pnlMain, label="USERS")
        stUsers.SetFont(font)

        # Make users list control
        lcUsers = wx.ListCtrl(pnlMain,style=wx.LC_REPORT|wx.SUNKEN_BORDER)
        lcUsers.Show(True)
        lcUsers.InsertColumn(0,"user")
        lcUsers.InsertColumn(1,"status")

        # Add all the components to the RIGHT sizer
        self.bsRight.Add((-1,10))
        self.bsRight.Add(stUsers, flag=wx.LEFT | wx.EXPAND | wx.ALIGN_CENTER | wx.ALIGN_CENTRE, border=5)
        self.bsRight.Add((-1,10))
        self.bsRight.Add(lcUsers, flag=wx.EXPAND)


        # Add the vertical sizers to the horizontal sizer
        self.bsMain.Add(self.bsLeft)
        self.bsMain.Add(self.bsRight)

        # Add the vertical sizer to the panel
        pnlMain.SetSizer(self.bsMain)
        self.bsMain.Layout()

if __name__ == '__main__':
    app = wx.App(False)
    frame = Screen(None, 'Layout')
    app.MainLoop()

注意:我很少需要调用 Refresh。我认为 Layout 会自动执行此操作。