Ross Wan's World!

Python, Ajax, PHP and Linux.

wxPython:布局管理器

Posted by Ross Wan 于 2008/03/16

       在 wxPython 有两种方法对窗口内的 widgets 进行布局:

  • 绝对定位(absolute positioning)
  • sizers

绝对定位(Absolute Positioning)

       首先必须了解一下因使用绝对定位而造成的问题:

  • 当窗口大小心改变的时候,窗口内的 widgets 的大小和位置不会改变。
  • 在不同的平台上有不同的布局表现。
  • 改变字体可能将程序的布局弄得一团糟。
  • 如果想改变布局,必须彻底地重设 widgets 的布局。

       下面的例子是一个简单编辑器的框架,使用了绝对定位布局,可以发现,当我们改变窗口大小, wx.TextCtrl 的大小并没有随之改变。

#!/usr/bin/python
# absolute.py

import wx

class Absolute(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(250, 180))
        panel = wx.Panel(self, -1)

        menubar = wx.MenuBar()
        file = wx.Menu()
        edit = wx.Menu()
        help = wx.Menu()

        menubar.Append(file, ‘&File’)
        menubar.Append(edit, ‘&Edit’)
        menubar.Append(help, ‘&Help’)
        self.SetMenuBar(menubar)

        wx.TextCtrl(panel, -1, pos=(-1, -1), size=(250, 150))

        self.Centre()
        self.Show(True)

app = wx.App(0)
Absolute(None, -1, ”)
app.MainLoop()

       在 wx.TextCtrl 的构造函数里使用了绝对定位的参数。

wx.TextCtrl(panel, -1, pos=(-1, -1), size=(250, 150))

使用 sizers

       sizers 可以解决上面使用绝对定位而造成的布局问题。下面是一些可选反对使用的 sizers:

  • wx.BoxSizer
  • wx.StaticBoxSizer
  • wx.GridSizer
  • wx.FlexGridSizer
  • wx.GridBagSizer

#!/usr/bin/python
# sizer.py

import wx

class Sizer(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(250, 180))

        menubar = wx.MenuBar()
        file = wx.Menu()
        edit = wx.Menu()
        help = wx.Menu()

        menubar.Append(file, ‘&File’)
        menubar.Append(edit, ‘&Edit’)
        menubar.Append(help, ‘&Help’)
        self.SetMenuBar(menubar)

        wx.TextCtrl(self, -1)

        self.Centre()
        self.Show(True)

app = wx.App(0)
Sizer(None, -1, ”)
app.MainLoop()

       你可能会问,在上面的代码中怎么没见到任何的 sizers 对象?实际上,wx.Frame 已经内建了一个 sizer,而且,只能放置一个 widget 到 wx.Frame 上。

wx.BoxSizer

       可以使放置其上的 widgets 成行或者成列排列,我们也可以放置 sizer 到另一个 sizer  上,以便于创建复杂的布局。

box = wx.BoxSizer(integer orient)
box.Add(wx.Window window, integer proportion=0, integer flag = 0, integer border = 0)

       参数 orientation(方向)可以是 wx.VERTICAL 或者 wx.HORIZONTAL。通过 Add() 方法可以添加 widgets 到 sizer 上。proportion(比例)参数。假设我们将三个按钮添加到一个 horizontal wx.BoxSizer 上,它们的 proportions 参数分别为 0、1、2。当窗口发生改变时, proportion 参数被设置为0的按钮不会在水平方向发生改变,而被设置为2 的按钮的大小始终是设置为1的按钮的两倍。border 参数用于控制边框,可以下面的值或者它们的组合值:

  • wx.LEFT
  • wx.RIGHT
  • wx.BOTTOM
  • wx.TOP
  •  wx.ALL

#!/usr/bin/python
# border.py

import wx

class Border(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(250, 200))

        panel = wx.Panel(self, -1)
        panel.SetBackgroundColour(‘#4f5049’)
        vbox = wx.BoxSizer(wx.VERTICAL)

        midPan = wx.Panel(panel, -1)
        midPan.SetBackgroundColour(‘#ededed’)

        vbox.Add(midPan, 1, wx.EXPAND | wx.ALL, 20)
        panel.SetSizer(vbox)
        self.Centre()
        self.Show(True)

app = wx.App()
Border(None, -1, ”)
app.MainLoop()

vbox.Add(midPan, 1, wx.EXPAND | wx.ALL, 20)

       上面的代码将为 midPan 面板的四边添加宽度为20像素的边框。

       wx.EXPAND 使 widget 占据分配到的全部空间。最后,我们也可以定义 widgets 的对齐方式:

  • wx.ALIGN_LEFT
  • wx.ALIGN_RIGHT
  • wx.ALIGN_TOP
  • wx.ALIGN_BOTTOM
  • wx.ALIGN_CENTER_VERTICAL
  • wx.ALIGN_CENTER_HORIZONTAL
  • wx.ALIGN_CENTER

实例(Go To Class)

       在下面的例子中,我们将引入几个重要的构思。

#!/usr/bin/python
# gotoclass.py

import wx

class GoToClass(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(390, 350))
        panel = wx.Panel(self, -1)

        font = wx.SystemSettings_GetFont(wx.SYS_SYSTEM_FONT)
        font.SetPointSize(9)

        vbox = wx.BoxSizer(wx.VERTICAL)

        hbox1 = wx.BoxSizer(wx.HORIZONTAL)
        st1 = wx.StaticText(panel, -1, ‘Class Name’)
        st1.SetFont(font)
        hbox1.Add(st1, 0, wx.RIGHT, 8)
        tc = wx.TextCtrl(panel, -1)
        hbox1.Add(tc, 1)
        vbox.Add(hbox1, 0, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, 10)

        vbox.Add((-1, 10))

        hbox2 = wx.BoxSizer(wx.HORIZONTAL)
        st2 = wx.StaticText(panel, -1, ‘Matching Classes’)
        st2.SetFont(font)
        hbox2.Add(st2, 0)
        vbox.Add(hbox2, 0, wx.LEFT | wx.TOP, 10)

        vbox.Add((-1, 10))

        hbox3 = wx.BoxSizer(wx.HORIZONTAL)
        tc2 = wx.TextCtrl(panel, -1, style=wx.TE_MULTILINE)
        hbox3.Add(tc2, 1, wx.EXPAND)
        vbox.Add(hbox3, 1, wx.LEFT | wx.RIGHT | wx.EXPAND, 10)

        vbox.Add((-1, 25))

        hbox4 = wx.BoxSizer(wx.HORIZONTAL)
        cb1 = wx.CheckBox(panel, -1, ‘Case Sensitive’)
        cb1.SetFont(font)
        hbox4.Add(cb1)
        cb2 = wx.CheckBox(panel, -1, ‘Nested Classes’)
        cb2.SetFont(font)
        hbox4.Add(cb2, 0, wx.LEFT, 10)
        cb3 = wx.CheckBox(panel, -1, ‘Non-Project classes’)
        cb3.SetFont(font)
        hbox4.Add(cb3, 0, wx.LEFT, 10)
        vbox.Add(hbox4, 0, wx.LEFT, 10)

        vbox.Add((-1, 25))

        hbox5 = wx.BoxSizer(wx.HORIZONTAL)
        btn1 = wx.Button(panel, -1, ‘Ok’, size=(70, 30))
        hbox5.Add(btn1, 0)
        btn2 = wx.Button(panel, -1, ‘Close’, size=(70, 30))
        hbox5.Add(btn2, 0, wx.LEFT | wx.BOTTOM , 5)
        vbox.Add(hbox5, 0, wx.ALIGN_RIGHT | wx.RIGHT, 10)

        panel.SetSizer(vbox)
        self.Centre()
        self.Show(True)

app = wx.App()
GoToClass(None, -1, ‘Go To Class’)
app.MainLoop()

       我们创建一个 vertical sizer,并且将5个 horizontal sizers 放置于上面。

 font = wx.SystemSettings_GetFont(wx.SYS_SYSTEM_FONT)
 font.SetPointSize(9)

       设置窗口字体的大小为9px。

实例(Find/Replace Dialog)

       下面是一个复杂的例子 ── 查找/替换对话框。

#!/usr/bin/python
# Find/Replace Dialog

import wx

class FindReplace(wx.Dialog):
    def __init__(self, parent, id, title):
        wx.Dialog.__init__(self, parent, id, title, size=(255, 365))

        vbox_top = wx.BoxSizer(wx.VERTICAL)
        panel = wx.Panel(self, -1)

        vbox = wx.BoxSizer(wx.VERTICAL)

        # panel1

        panel1 = wx.Panel(panel, -1)
        grid1 = wx.GridSizer(2, 2)
        grid1.Add(wx.StaticText(panel1, -1, ‘Find: ‘, (5, 5)), 0,  wx.ALIGN_CENTER_VERTICAL)
        grid1.Add(wx.ComboBox(panel1, -1, size=(120, -1)))
        grid1.Add(wx.StaticText(panel1, -1, ‘Replace with: ‘, (5, 5)), 0, wx.ALIGN_CENTER_VERTICAL)
        grid1.Add(wx.ComboBox(panel1, -1, size=(120, -1)))

        panel1.SetSizer(grid1)
        vbox.Add(panel1, 0, wx.BOTTOM | wx.TOP, 9)

        # panel2

        panel2 = wx.Panel(panel, -1)
        hbox2 = wx.BoxSizer(wx.HORIZONTAL)

        sizer21 = wx.StaticBoxSizer(wx.StaticBox(panel2, -1, ‘Direction’), orient=wx.VERTICAL)
        sizer21.Add(wx.RadioButton(panel2, -1, ‘Forward’, style=wx.RB_GROUP))
        sizer21.Add(wx.RadioButton(panel2, -1, ‘Backward’))
        hbox2.Add(sizer21, 1, wx.RIGHT, 5)

        sizer22 = wx.StaticBoxSizer(wx.StaticBox(panel2, -1, ‘Scope’), orient=wx.VERTICAL)
        # we must define wx.RB_GROUP style, otherwise all 4 RadioButtons would be mutually exclusive
        sizer22.Add(wx.RadioButton(panel2, -1, ‘All’, style=wx.RB_GROUP))
        sizer22.Add(wx.RadioButton(panel2, -1, ‘Selected Lines’))
        hbox2.Add(sizer22, 1)

        panel2.SetSizer(hbox2)
        vbox.Add(panel2, 0, wx.BOTTOM, 9)

        # panel3

        panel3 = wx.Panel(panel, -1)
        sizer3 = wx.StaticBoxSizer(wx.StaticBox(panel3, -1, ‘Options’), orient=wx.VERTICAL)
        vbox3 = wx.BoxSizer(wx.VERTICAL)
        grid = wx.GridSizer(3, 2, 0, 5)
        grid.Add(wx.CheckBox(panel3, -1, ‘Case Sensitive’))
        grid.Add(wx.CheckBox(panel3, -1, ‘Wrap Search’))
        grid.Add(wx.CheckBox(panel3, -1, ‘Whole Word’))
        grid.Add(wx.CheckBox(panel3, -1, ‘Incremental’))
        vbox3.Add(grid)
        vbox3.Add(wx.CheckBox(panel3, -1, ‘Regular expressions’))
        sizer3.Add(vbox3, 0, wx.TOP, 4)

        panel3.SetSizer(sizer3)
        vbox.Add(panel3, 0, wx.BOTTOM, 15)

        # panel4

        panel4 = wx.Panel(panel, -1)
        sizer4 = wx.GridSizer(2, 2, 2, 2)
        sizer4.Add(wx.Button(panel4, -1, ‘Find’, size=(120, -1)))
        sizer4.Add(wx.Button(panel4, -1, ‘Replace/Find’, size=(120, -1)))
        sizer4.Add(wx.Button(panel4, -1, ‘Replace’, size=(120, -1)))
        sizer4.Add(wx.Button(panel4, -1, ‘Replace All’, size=(120, -1)))

        panel4.SetSizer(sizer4)
        vbox.Add(panel4, 0, wx.BOTTOM, 9)

        # panel5

        panel5 = wx.Panel(panel, -1)
        sizer5 = wx.BoxSizer(wx.HORIZONTAL)
        sizer5.Add((191, -1), 1, wx.EXPAND | wx.ALIGN_RIGHT)
        sizer5.Add(wx.Button(panel5, -1, ‘Close’, size=(50, -1)))

        panel5.SetSizer(sizer5)
        vbox.Add(panel5, 1, wx.BOTTOM, 9)

        vbox_top.Add(vbox, 1, wx.LEFT, 5)
        panel.SetSizer(vbox_top)

        self.Centre()
        self.ShowModal()
        self.Destroy()

app = wx.App()
FindReplace(None, -1, ‘Find/Replace’)
app.MainLoop()

        备注:对于 Windows 用户,请在 ShowModal() 行前加入 self.SetClientSize(panel.GetBestSize()) 行。

wx.GridSizer

wx.GridSizer(int rows=1, int cols=0, int vgap=0, int hgap=0)  

       这是 wx.GridSizer 的构造函数。分别定义布局表格的行列数以及行列的大小。

       下面使用 wx.GridSizer 来构造一个计算器的基本骨架。

#!/usr/bin/python
# gridsizer.py

import wx

class GridSizer(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(300, 250))

        menubar = wx.MenuBar()
        file = wx.Menu()
        file.Append(1, ‘&Quit’, ‘Exit Calculator’)
        menubar.Append(file, ‘&File’)
        self.SetMenuBar(menubar)

        self.Bind(wx.EVT_MENU, self.OnClose, id=1)

        sizer = wx.BoxSizer(wx.VERTICAL)
        self.display = wx.TextCtrl(self, -1, ”,  style=wx.TE_RIGHT)
        sizer.Add(self.display, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 4)
        gs = wx.GridSizer(4, 4, 3, 3)

        gs.AddMany( [(wx.Button(self, -1, ‘Cls’), 0, wx.EXPAND),
            (wx.Button(self, -1, ‘Bck’), 0, wx.EXPAND),
            (wx.StaticText(self, -1, ”), 0, wx.EXPAND),
            (wx.Button(self, -1, ‘Close’), 0, wx.EXPAND),
            (wx.Button(self, -1, ‘7’), 0, wx.EXPAND),
            (wx.Button(self, -1, ‘8’), 0, wx.EXPAND),
            (wx.Button(self, -1, ‘9’), 0, wx.EXPAND),
            (wx.Button(self, -1, ‘/’), 0, wx.EXPAND),
            (wx.Button(self, -1, ‘4’), 0, wx.EXPAND),
            (wx.Button(self, -1, ‘5’), 0, wx.EXPAND),
            (wx.Button(self, -1, ‘6’), 0, wx.EXPAND),
            (wx.Button(self, -1, ‘*’), 0, wx.EXPAND),
            (wx.Button(self, -1, ‘1’), 0, wx.EXPAND),
            (wx.Button(self, -1, ‘2’), 0, wx.EXPAND),
            (wx.Button(self, -1, ‘3’), 0, wx.EXPAND),
            (wx.Button(self, -1, ‘-‘), 0, wx.EXPAND),
            (wx.Button(self, -1, ‘0’), 0, wx.EXPAND),
            (wx.Button(self, -1, ‘.’), 0, wx.EXPAND),
            (wx.Button(self, -1, ‘=’), 0, wx.EXPAND),
            (wx.Button(self, -1, ‘+’), 0, wx.EXPAND) ])

        sizer.Add(gs, 1, wx.EXPAND)
        self.SetSizer(sizer)
        self.Centre()
        self.Show(True)

    def OnClose(self, event):
        self.Close()

app = wx.App()
GridSizer(None, -1, ‘GridSizer’)
app.MainLoop()

       注意,我们在 Bck 和 Close 按钮之间放置一个空白的 wx.StaticText,这是布局上的一个有用技巧。

       例子中的 AddMany() 方法可以一次过放置多个 widgets 到 sizer 上。

 AddMany(list items)

       widgets 放置在布局表格上是按一定顺序的,先放满第一行,再放置第二行…如此类推。

wx.FlexGridSizer

       wx.FlexGridSizer 跟 wx.GridSizer 相似,但提供更多的灵活性。在 wx.GridSizer 中,所有的单元格都必须大小相同。而在 wx.FlexGridSizer 中,同行的单元格的高度相同,同列的单元格的宽度相同,而不同的列和行可以高宽度不同。

 wx.FlexGridSizer(int rows=1, int cols=0, int vgap=0, int hgap=0)

       这是 wx.FlesGridSizer 的构造函数,跟 wx.GridSizer 的构造函数相似。

#!/usr/bin/python
# flexgridsizer.py

import wx

class FlexGridSizer(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(290, 250))

        panel = wx.Panel(self, -1)

        hbox = wx.BoxSizer(wx.HORIZONTAL)

        fgs = wx.FlexGridSizer(3, 2, 9, 25)

        title = wx.StaticText(panel, -1, ‘Title’)
        author = wx.StaticText(panel, -1, ‘Author’)
        review = wx.StaticText(panel, -1, ‘Review’)

        tc1 = wx.TextCtrl(panel, -1)
        tc2 = wx.TextCtrl(panel, -1)
        tc3 = wx.TextCtrl(panel, -1, style=wx.TE_MULTILINE)

        fgs.AddMany([(title), (tc1, 1, wx.EXPAND), (author), (tc2, 1, wx.EXPAND),
            (review, 1, wx.EXPAND), (tc3, 1, wx.EXPAND)])

        fgs.AddGrowableRow(2, 1)
        fgs.AddGrowableCol(1, 1)

        hbox.Add(fgs, 1, wx.ALL | wx.EXPAND, 15)
        panel.SetSizer(hbox)

        self.Centre()
        self.Show(True)

app = wx.App()
FlexGridSizer(None, -1, ‘FlexGridSizer’)
app.MainLoop()

       我们设置第三行和第二列为可变大小,这样,当窗口大小改变时,文本控件也随之改变。当然,不要忘记设置相应的 widgets 的 wx.EXPAND。

wx.GridBagSizer

       这是 wxPython 中最复杂的一个 sizer,它可以精确的定位 widgets。下面是 wx.GridBagSizer 的构造函数:

 wx.GridBagSizer(integer vgap, integer hgap)

       通过 Add() 方法放置 widgets:

Add(self, item, tuple pos, tuple span=wx.DefaultSpan, integer flag=0, integer border=0, userData=None)

       pos 参数指定放置于虚拟表格的位置 ── 左上角为 (0,0)。span 参数是一个可选参数,指定 widgets 的跨度,例如,(3,2) 表示 widget 跨越 3 行 2 列。falg 和 border 参数跟 wx.BoxSizer 的相同。如果想设置可改变的表格,可以使用下面的方法:

 AddGrowableRow(integer row)
 AddGrowableCol(integer col)

实例(Rename dialog)

       这是一个简单的示例。我们不必因为 wx.GridBagSizer 的过于复杂而担心,一旦我们理解它的原理,使用起来也会很简单的。

#!/usr/bin/python
# rename.py

import wx

class Rename(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(320, 130))

        panel = wx.Panel(self, -1)
        sizer = wx.GridBagSizer(4, 4)

        text = wx.StaticText(panel, -1, ‘Rename To’)
        sizer.Add(text, (0, 0), flag=wx.TOP | wx.LEFT | wx.BOTTOM, border=5)

        tc = wx.TextCtrl(panel, -1)
        sizer.Add(tc, (1, 0), (1, 5), wx.EXPAND | wx.LEFT | wx.RIGHT, 5)

        buttonOk = wx.Button(panel, -1, ‘Ok’, size=(90, 28))
        buttonClose = wx.Button(panel, -1, ‘Close’, size=(90, 28))
        sizer.Add(buttonOk, (3, 3))
        sizer.Add(buttonClose, (3, 4), flag=wx.RIGHT | wx.BOTTOM, border=5)

        sizer.AddGrowableCol(1)
        sizer.AddGrowableRow(2)
        panel.SetSizerAndFit(sizer)
        self.Centre()
        self.Show(True)

app = wx.App()
Rename(None, -1, ‘Rename Dialog’)
app.MainLoop()

 text = wx.StaticText(panel, -1, ‘Rename To’)
 sizer.Add(text, (0, 0), flag=wx.TOP | wx.LEFT | wx.BOTTOM, border=5)

       将文本 “Rename to”放于窗口的左上角,因此将 pos 指定为 (0,0)。

 tc = wx.TextCtrl(panel, -1)
 sizer.Add(tc, (1, 0), (1, 5), wx.EXPAND | wx.LEFT | wx.RIGHT, 5)

       将文本输入框放于第二行的始端(1,0) ── 紧记,是用 0 开始计数的。同时文本框跨越1行5列(1,5)。

 sizer.Add(buttonOk, (3, 3))
 sizer.Add(buttonClose, (3, 4), flag=wx.RIGHT | wx.BOTTOM, border=5)

       在第4行放置两个按钮(第三行我们空着),分别放于第4列和第5列。

实例(Open Resource)

#!/usr/bin/python
# openresource.py

import wx

class OpenResource(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(400, 500))

        panel = wx.Panel(self, -1)
        sizer = wx.GridBagSizer(4, 4)

        text1 = wx.StaticText(panel, -1, ‘Select a resource to open’)
        sizer.Add(text1, (0, 0), flag=wx.TOP | wx.LEFT | wx.BOTTOM, border=5)

        tc = wx.TextCtrl(panel, -1)
        sizer.Add(tc, (1, 0), (1, 3), wx.EXPAND | wx.LEFT | wx.RIGHT, 5)

        text2 = wx.StaticText(panel, -1, ‘Matching resources’)
        sizer.Add(text2, (2, 0), flag=wx.TOP | wx.LEFT | wx.BOTTOM, border=5)

        list1 = wx.ListBox(panel, -1, style=wx.LB_ALWAYS_SB)
        sizer.Add(list1, (3, 0), (5, 3), wx.EXPAND | wx.LEFT | wx.RIGHT, 5)

        text3 = wx.StaticText(panel, -1, ‘In Folders’)
        sizer.Add(text3, (8, 0), flag=wx.TOP | wx.LEFT | wx.BOTTOM, border=5)

        list2 = wx.ListBox(panel, -1, style=wx.LB_ALWAYS_SB)
        sizer.Add(list2, (9, 0), (3, 3), wx.EXPAND | wx.LEFT | wx.RIGHT, 5)

        cb = wx.CheckBox(panel, -1, ‘Show derived resources’)
        sizer.Add(cb, (12, 0), flag=wx.LEFT | wx.RIGHT, border=5)

        buttonOk = wx.Button(panel, -1, ‘OK’, size=(90, 28))
        buttonCancel = wx.Button(panel, -1, ‘Cancel’, size=(90, 28))
        sizer.Add(buttonOk, (14, 1))
        sizer.Add(buttonCancel, (14, 2), flag=wx.RIGHT | wx.BOTTOM, border=5)

        help = wx.BitmapButton(panel, -1, wx.Bitmap(‘icons/help16.png’), style=wx.NO_BORDER)
        sizer.Add(help, (14, 0), flag=wx.LEFT, border=5)

        sizer.AddGrowableCol(0)
        sizer.AddGrowableRow(3)
        sizer.AddGrowableRow(9)
        sizer.SetEmptyCellSize((5, 5))
        panel.SetSizer(sizer)

        self.Centre()
        self.Show(True)

app = wx.App()
OpenResource(None, -1, ‘Open Resource’)
app.MainLoop()

实例(Create new class)

#!/usr/bin/python
# newclass.py

import wx

class NewClass(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title)

        panel = wx.Panel(self, -1)
        sizer = wx.GridBagSizer(0, 0)

        text1 = wx.StaticText(panel, -1, ‘Java Class’)
        sizer.Add(text1, (0, 0), flag=wx.TOP | wx.LEFT | wx.BOTTOM, border=15)

        icon = wx.StaticBitmap(panel, -1, wx.Bitmap(‘icons/exec.png’))
        sizer.Add(icon, (0, 4), flag=wx.LEFT,  border=45)

        line = wx.StaticLine(panel, -1 )
        sizer.Add(line, (1, 0), (1, 5), wx.TOP | wx.EXPAND, -15)

        text2 = wx.StaticText(panel, -1, ‘Name’)
        sizer.Add(text2, (2, 0), flag=wx.LEFT, border=10)

        tc1 = wx.TextCtrl(panel, -1, size=(-1, 30))
        sizer.Add(tc1, (2, 1), (1, 3), wx.TOP | wx.EXPAND, -5)

        text3 = wx.StaticText(panel, -1, ‘Package’)
        sizer.Add(text3, (3, 0), flag= wx.LEFT | wx.TOP, border=10)

        tc2 = wx.TextCtrl(panel, -1)
        sizer.Add(tc2, (3, 1), (1, 3), wx.TOP | wx.EXPAND, 5)

        button1 = wx.Button(panel, -1, ‘Browse…’, size=(-1, 30))
        sizer.Add(button1, (3, 4), (1, 1), wx.TOP | wx.LEFT | wx.RIGHT , 5)

        text4 = wx.StaticText(panel, -1, ‘Extends’)
        sizer.Add(text4, (4, 0), flag=wx.TOP | wx.LEFT, border=10)

        combo = wx.ComboBox(panel, -1, )
        sizer.Add(combo, (4, 1), (1, 3), wx.TOP | wx.EXPAND,  5)

        button2 = wx.Button(panel, -1, ‘Browse…’, size=(-1, 30))
        sizer.Add(button2, (4, 4), (1, 1), wx.TOP | wx.LEFT | wx.RIGHT , 5)

        sb = wx.StaticBox(panel, -1, ‘Optional Attributes’)
        boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
        boxsizer.Add(wx.CheckBox(panel, -1, ‘Public’), 0, wx.LEFT | wx.TOP, 5)
        boxsizer.Add(wx.CheckBox(panel, -1, ‘Generate Default Constructor’), 0,  wx.LEFT, 5)
        boxsizer.Add(wx.CheckBox(panel, -1, ‘Generate Main Method’), 0, wx.LEFT | wx.BOTTOM, 5)
        sizer.Add(boxsizer, (5, 0), (1, 5), wx.EXPAND | wx.TOP | wx.LEFT | wx.RIGHT , 10)
        button3 = wx.Button(panel, -1, ‘Help’, size=(-1, 30))
        sizer.Add(button3, (7, 0), (1, 1),  wx.LEFT, 10)

        button4 = wx.Button(panel, -1, ‘Ok’, size=(-1, 30))
        sizer.Add(button4, (7, 3), (1, 1),  wx.LEFT, 10)

        button5 = wx.Button(panel, -1, ‘Cancel’, size=(-1, 30))
        sizer.Add(button5, (7, 4), (1, 1),  wx.LEFT | wx.BOTTOM | wx.RIGHT, 10)

        sizer.AddGrowableCol(2)
        sizer.Fit(self)
        panel.SetSizer(sizer)
        self.Centre()
        self.Show(True)

app = wx.App()
NewClass(None, -1, ‘Create Java Class’)
app.MainLoop()

       注意,这里我们使用负数来设置 top border,这相当于设置 bottom border 为15px。

sizer.Fit(self)

       确保窗口的大小可以覆盖所有 widgets。

Advertisements

一条回应 to “wxPython:布局管理器”

  1. Ross Wan said

    翻译自:The wxPython tutorial

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s

 
%d 博主赞过: