在 wxPython 中,BoxSizer 是一种常用的布局管理器,可以用来将窗口控件垂直或水平排列,从而实现整齐的布局。BoxSizer 分为 wx.BoxSizer(wx.HORIZONTAL)wx.BoxSizer(wx.VERTICAL) 两种,分别用于水平和垂直布局。

如何在wxPython GUI中使用BoxSizers实现整齐布局_输入框

1、问题背景

在开发一个wxPython GUI应用程序时,我遇到一个问题,希望实现如下布局:

labelOne | inputOne
lblTwo | inputTwo
lblThree | inputThree
  • 1.
  • 2.
  • 3.

其中,文本标签左对齐,输入框全部对齐。我在wxPython演示代码中看到了这种布局,但是它们都使用了FlexGridSizer,而我只想使用BoxSizers。原因是BoxSizers更简单,而且我对任何类型的Sizers都知之甚少。我尝试过将输入和文本放在两个垂直的Sizers中,然后将它们放入一个水平的Sizers,但这样做不起作用,因为文本与输入框不一致。我还尝试过这样做,并且还将每个文本和输入配对放在一个Sizer中,结果更糟。有什么建议吗?

2、解决方案

以下是一个使用BoxSizers实现上述布局的简单示例:

import wx

class MyForm(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, "Tutorial")

        # Add a panel so it looks the correct on all platforms
        panel = wx.Panel(self, wx.ID_ANY)

        # create the labels
        lblOne = wx.StaticText(panel, label="labelOne", size=(60,-1))
        lblTwo = wx.StaticText(panel, label="lblTwo", size=(60,-1))
        lblThree = wx.StaticText(panel, label="lblThree", size=(60,-1))

        # create the text controls
        txtOne = wx.TextCtrl(panel)
        txtTwo = wx.TextCtrl(panel)
        txtThree = wx.TextCtrl(panel)

        # create some sizers
        mainSizer = wx.BoxSizer(wx.VERTICAL)
        lineOneSizer = wx.BoxSizer(wx.HORIZONTAL)
        lineTwoSizer = wx.BoxSizer(wx.HORIZONTAL)
        lineThreeSizer = wx.BoxSizer(wx.HORIZONTAL)

        # add widgets to sizers
        lineOneSizer.Add(lblOne, 0, wx.ALL|wx.ALIGN_LEFT, 5)
        lineOneSizer.Add(txtOne, 0, wx.ALL, 5)
        lineTwoSizer.Add(lblTwo, 0, wx.ALL|wx.ALIGN_LEFT, 5)
        lineTwoSizer.Add(txtTwo, 0, wx.ALL, 5)
        lineThreeSizer.Add(lblThree, 0, wx.ALL|wx.ALIGN_LEFT, 5)
        lineThreeSizer.Add(txtThree, 0, wx.ALL, 5)

        mainSizer.Add(lineOneSizer)
        mainSizer.Add(lineTwoSizer)
        mainSizer.Add(lineThreeSizer)

        panel.SetSizer(mainSizer)

# Run the program
if __name__ == "__main__":
    app = wx.App(False)
    frame = MyForm()
    frame.Show()
    app.MainLoop()
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.

这是一种实现上述布局的方法,但它有些混乱。以下是一个经过重构的版本:

import wx

class MyForm(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, "Tutorial")

        # create the main sizer
        self.mainSizer = wx.BoxSizer(wx.VERTICAL)

        # Add a panel so it looks the correct on all platforms
        self.panel = wx.Panel(self, wx.ID_ANY)

        lbls = ["labelOne", "lblTwo", "lblThree"]
        for lbl in lbls:
            self.buildLayout(lbl)
        self.panel.SetSizer(self.mainSizer)

    #----------------------------------------------------------------------
    def buildLayout(self, text):
        """"""
        lblSize = (60,-1)
        lbl = wx.StaticText(self.panel, label=text, size=lblSize)
        txt = wx.TextCtrl(self.panel)

        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(lbl, 0, wx.ALL|wx.ALIGN_LEFT, 5)
        sizer.Add(txt, 0, wx.ALL, 5)
        self.mainSizer.Add(sizer)

# Run the program
if __name__ == "__main__":
    app = wx.App(False)
    frame = MyForm()
    frame.Show()
    app.MainLoop()
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.

对于大多数布局,除了最基本的布局之外,我们通常无法避免使用多种类型的Sizers才能实现我们的设计。这里有一个关于Sizers的很好教程。