wxPython入门指南

3

我在使用wxPython中的sizers布局表单方面遇到了一些挑战,如果有人能为我提供一个在图像中展示的布局方案,我将不胜感激。

样例表单

请分享相关资源。

谢谢。


你用什么工具创建了模型? - Marcus Junius Brutus
2个回答

7
我建议在设计复杂的GUI时不要手动调整大小。请使用wxglade,然后手动自定义。这样做只需要15分钟,但可能会有错误(我没有填写列表控件,抱歉)。我遵循以下步骤:
1) Add a Frame widget, select a wx.Frame.  

2) Customize wx.Frame properties:  
     Give the Frame a MenuBar (the property dialog for the menubar appears).  
     Customize MenuBar: Add File, Edit...  
     Go back to the Frame properties' View (click the Frame icon on the wxglade Tree View).  
     (not nice but it's the way I found to go in and out from Menu and StatusBar dialogs).  
     Give the wx.Frame a StatusBar. Go back (click the Frame icon in the wxglade Tree View).  

3) Create 3 vertical slots from the default BoxSizer (right-click on the sizer + add * 3)
      1st slot: 
          Add a BoxSizer with 5 horizontal slots
          Set proportion=0 to the sizer, set border=5 and mark wxALL
          Add 4 Buttons and a Spacer in those slots
          Mark EXPAND and set proportion=1 in the Spacer properties.

      2nd slot:
          Add a SplitterWindow. Select Vertical type.
          Optionally set border=5 with wxALL
          Add a BoxSizer to each section of the SplitterWindow
          At its left, add a ListCtrl
          At its right, add a NoteBook
          Customize NoteBook:
              Add 4 sheets.
              Add BoxSizer with 2 vertical slots to first notebook sheet.
                  1st slot: insert a wx.Panel.
                  2nd slot: add a BoxSizer with 3 horizontal slots.
                      Set proportion=0 to the sizer.
                      Add 2 buttons and 1 Spacer in those slots.
                      Mark EXPAND and set proportion=1 in the Spacer properties.

      3rd slot:
          Add a BoxSizer with 5 horizontal slots.
          Set proportion=0 to the sizer, set border=5 with wxALL
          Add 2 Buttons, 1 Spacer and 2 Buttons more.
          Mark EXPAND and set proportion=1 in the Spacer properties.

4) Give background colour to the Frame.
  (Choose wisely, you still have 5 minutes left of the 15 allotted).

最后,自定义标签、大小和部件名称等。
将wxGlade文件保存以备将来更改,并生成Python文件(在顶部应用程序对话框中)。
提示:不要修改生成的文件,而是在另一个文件中导入并子类化您的Frame以编写其功能。

最后一点注意事项:根据我的经验,在Linux和Windows中使用sizers和背景有一些差异。在Linux中,不要像步骤3中所示使用默认Frame的BoxSizer。相反,在其上添加wx.Panel,为该Panel添加BoxSizer,并继续从此sizer构建。


太好了!谢谢。我试图理解 wxGlade,但很费劲,这个网站帮了我大忙:http://wiki.wxpython.org/BoxSizerFromTheGroundUp。有趣的是,我发现手动绘制表单比使用设计工具更容易。如果你可以在15分钟内完成,我会再试一次。 - gath
@gath,一旦你有了你的框架视图,你只需要按照一个顺序进行操作:插入具有n个插槽的sizer,然后对于每个插槽,要么用小部件填充插槽并自定义它,要么添加另一个sizer(并在此处递归)。感谢您提供的链接,这对我来说是新的。您是否也查看了wxglade软件包中包含的教程和文档?该工具相对简单,但同时非常强大(或因为如此)。一旦您习惯了自定义的技巧,主要问题,即花费更多时间构建复杂的GUI的问题,就是选择颜色组合。 - joaquin
非常感谢!我按照你的指示操作了,我同意,使用Glade制作复杂GUI确实更快!谢谢。顺便问一下,你有在Linux上安装wxWidgets/wxPython吗?我的尝试简直是一场痛苦!! - gath
我在所有的Ubuntu电脑上都安装了它。不确定它是否是默认安装的,还是我使用Ubuntu软件管理器从Ubuntu官方仓库中获取的,但肯定没有任何问题。您不需要使用任何手动Linux控制台安装指令。否则我会记得的。我刚刚检查了一下,对于Ubuntu 11.4(Natty),Ubuntu仓库提供wxPython 2.8.12.0。 - joaquin

3

出于好奇,我决定手工编写类似的东西需要多长时间。大约花了我35分钟左右。我跳过了菜单栏。哦,无妨。以下是代码:

import wx

########################################################################
class TabPanel(wx.Panel):
    """"""

    #----------------------------------------------------------------------
    def __init__(self, parent):
        """Constructor"""
        wx.Panel.__init__(self, parent)

        btnOne = wx.Button(self, label="button_10")
        btnTwo = wx.Button(self, label="button_11")

        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(btnOne, 0, wx.ALIGN_BOTTOM)
        sizer.Add(btnTwo, 0, wx.ALIGN_BOTTOM)
        self.SetSizer(sizer)

########################################################################
class LeftPanel(wx.Panel):
    """"""

    #----------------------------------------------------------------------
    def __init__(self, parent):
        """Constructor"""
        wx.Panel.__init__(self, parent)
        self.list_ctrl = wx.ListCtrl(self, size=(-1,100),
                         style=wx.LC_REPORT
                         |wx.BORDER_SUNKEN
                         )
        self.list_ctrl.InsertColumn(0, 'Subject')
        self.list_ctrl.InsertColumn(1, 'Due')
        self.list_ctrl.InsertColumn(2, 'Location', width=125)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.list_ctrl, 1, wx.EXPAND)
        self.SetSizer(sizer)

########################################################################
class RightPanel(wx.Panel):
    """"""

    #----------------------------------------------------------------------
    def __init__(self, parent):
        """Constructor"""
        wx.Panel.__init__(self, parent)

        notebook = wx.Notebook(self)
        page1 = TabPanel(notebook)
        page2 = TabPanel(notebook)
        page3 = TabPanel(notebook)

        notebook.AddPage(page1, "Page_1")
        notebook.AddPage(page2, "Page_2")
        notebook.AddPage(page3, "Page_3")

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(notebook, 1, wx.EXPAND)
        self.SetSizer(sizer)

########################################################################
class MainPanel(wx.Panel):
    """"""

    #----------------------------------------------------------------------
    def __init__(self, parent):
        """Constructor"""
        wx.Panel.__init__(self, parent)

        mainSizer = wx.BoxSizer(wx.VERTICAL)
        btnSizer = wx.BoxSizer(wx.HORIZONTAL)

        # create row of buttons
        for i in range(4):
            btn = wx.Button(self, label="button_%s" % i)
            btnSizer.Add(btn, 0, wx.ALL, 5)
        mainSizer.Add(btnSizer)

        # create splitter
        splitter = wx.SplitterWindow(self)
        leftPanel = LeftPanel(splitter)
        rightPanel = RightPanel(splitter)
        splitter.SplitVertically(leftPanel, rightPanel)
        mainSizer.Add(splitter, 1, wx.EXPAND)

        # add second row of buttons
        btnSizer2 = wx.BoxSizer(wx.HORIZONTAL)
        btn5 = wx.Button(self, label="button_5")
        btn6 = wx.Button(self, label="button_6")
        btn7 = wx.Button(self, label="button_7")
        btn8 = wx.Button(self, label="button_8")
        btnSizer2.Add(btn5)
        btnSizer2.Add(btn6)
        btnSizer2.Add((1,1), 1, wx.EXPAND)
        btnSizer2.Add(btn7)
        btnSizer2.Add(btn8)
        mainSizer.Add(btnSizer2)

        self.SetSizer(mainSizer)


########################################################################
class MainFrame(wx.Frame):
    """"""

    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, None, title="Sample", size=(600,800))
        panel = MainPanel(self)
        statusbar = self.CreateStatusBar()
        statusbar.SetStatusText("Test")
        self.Show()

if __name__ == "__main__":
    app = wx.App(False)
    frame = MainFrame()
    app.MainLoop()

太好了!使用wxglade可视化设计和自动生成代码,您可以获得更多优势:1)生成的代码更加扁平化,所有GUI都在一个类中。这使得小部件可以直接从子类访问,而无需繁琐的继承层次结构。这似乎违反了代码结构、代码重用等原则。但我认为这在这里并不重要,因为如果您想要重用GUI中的某个复杂面板,只需在两个打开的wxglade设计视图之间复制/粘贴小部件(我已经这样做了,效果很棒!)或在设计视图中重新设计您的GUI并生成新的GUI类即可。 - joaquin
  1. 它从不会忘记设置样式、self或ID:第一次尝试就能运行。
  2. 代码的稳定性还有助于进一步编码,例如将小部件事件绑定到函数、从主类动态更改某些属性(你需要一些self来实现,Mike)等。
- joaquin
我没有将所有的小部件都变成属性,因为我不需要。大多数情况下,你也不需要将按钮变成类属性。是的,把所有东西放在一个类中很方便,但我觉得这样很乱。我认为我在这里没有使用任何笨重的继承,但每个人都有自己的编码风格。我曾经把所有东西都放在一个类中,但现在我尽量不这样做,因为我喜欢重用我的代码,并且在自己的类中调整大小更容易,至少在我的想法中是这样的。 - Mike Driscoll

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接