总目录:wxPython 教程目录 本节内容:wxPython 布局 管理 本节译自:zetcode 上一篇:wxpython 教程(三): 菜单与工具栏 下一篇:wxpython 教程 (五): 事件
应用包含多个 widgets,这些 widgets 都被放置在容器内,我们必须正确的对 widgets 的位置进行管理,这不是一件容易的事情。在 wxPython 布局 中,可以使用绝对定位或者使用 sizers 对 widgets 进行位置管理。
绝对定位
在 wxPython 布局 时,我们可以对 widgets 在像素水平对 widgets 进行定位,但是这样做的缺点有:
- 如果我们调整窗口大小时,widget 的尺寸和位置不会随之改变。
- 在不同的系统上,应用的界面不一致。
- 修改应用字体会使界面变得混乱。
- 如果我们决定修改布局,必须重头开始,这非常冗长耗时。
但是有些场景仍然需要绝对定位。比如,小型的测试样例。但是,实际情况是程序员大多会使用 sizers ,它是 wxPython 的布局管理器。
下面的例子中,我们创建一个文本编辑器的框架。在修改窗口大小时,文字输入区域 wx.TextCtrl 的大小不会跟着改变。
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 | #!/usr/bin/python # -*- coding: utf-8 -*- # absolute.py import wx class Example(wx.Frame): def __init__( self , parent, title): super (Example, self ).__init__(parent, title = title, size = ( 260 , 180 )) self .InitUI() self .Centre() self .Show() def InitUI( self ): panel = wx.Panel( self , - 1 ) menubar = wx.MenuBar() filem = wx.Menu() editm = wx.Menu() helpm = wx.Menu() menubar.Append(filem, '&File' ) menubar.Append(editm, '&Edit' ) menubar.Append(helpm, '&Help' ) self .SetMenuBar(menubar) wx.TextCtrl(panel, pos = ( 3 , 3 ), size = ( 250 , 150 )) if __name__ = = '__main__' : app = wx.App() Example( None , title = '') app.MainLoop() |
在上面带锤子中,我们使用绝对坐标放置了一个文本控制区域。
1 | wx.TextCtrl(panel, pos = ( 3 , 3 ), size = ( 250 , 150 )) |
我们在wx.TextCtrl的构造函数中使用了绝对定位,x=3,y=3,宽度250px,高度150px。
图:修改大小之前
图:修改大小之后
使用sizers
使用sizers比使用绝对定位更通用更灵活,可供选择的 sizer 类型有:
- wx.BoxSizer
- wx.StaticBoxSizer
- wx.GridSizer
- wx.FlexGridSizer
- wx.GridBagSizer
下面的例子使用了内置(built-in)的 sizer。
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 | #!/usr/bin/python # -*- coding: utf-8 -*- # sizer.py import wx class Example(wx.Frame): def __init__( self , parent, title): super (Example, self ).__init__(parent, title = title, size = ( 260 , 180 )) self .InitUI() self .Centre() self .Show() def InitUI( self ): menubar = wx.MenuBar() filem = wx.Menu() editm = wx.Menu() helpm = wx.Menu() menubar.Append(filem, '&File' ) menubar.Append(editm, '&Edit' ) menubar.Append(helpm, '&Help' ) self .SetMenuBar(menubar) wx.TextCtrl( self ) if __name__ = = '__main__' : app = wx.App() Example( None , title = '') app.MainLoop() |
在这个例子中,没有显式的 sizer 定义。我们把 wx.TextCtrl 放入 wx.Frame,它有一个内置的 sizer,但是只允许放置一个 widget ,多于一个的话会得到混乱的布局。放入的子 widget 占用了所有剩余空间,除去边框、菜单、工具栏和状态栏。
图:调整大小之前
图:调整大小之后
wx.BoxSizer
BoxSizer 允许我们按行或者列来排列多个 widget ,同时也允许 sizer 的嵌套,这时的我们可以构造出非常复杂的布局。
1 2 | box = wx.BoxSizer(integer orient) box.Add(wx.Window window, integer proportion = 0 , integer flag = 0 , integer border = 0 ) |
wx.BoxSizer 的参数 orient 代表方向,可以是 wx.VERTICAL 或者 wx.HORIZONTAL ,代表竖直或水平。通过Add()函数可以添加widgets ,我们详细了解一下其中的参数。
proportion 参数表示在给定的方向中, widget 安装怎么的比例来调整大小。加入我们有三个按钮,对应的 proportion 参数分别为0,1和2。它们被放入一个水平的 wx.BoxSizer 中。在水平方向, proportion 为0的按钮不会改变大小,proportion 为2的按钮会改变为 proportion 为1按钮的两倍大小。
flag 参数可以更具体的定义 widget 在wx.BoxSizer中的行为。通过flag,我们可以控制 widget 之间的距离。我们需要对不同方向的边界进行定义,不同方向之间可以通过竖线符号|组合。可选的方向为:
- wx.LEFT
- wx.RIGHT
- wx.BOTTOM
- wx.TOP
- wx.ALL
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 | #!/usr/bin/python # -*- coding: utf-8 -*- # border.py import wx class Example(wx.Frame): def __init__( self , parent, title): super (Example, self ).__init__(parent, title = title, size = ( 260 , 180 )) self .InitUI() self .Centre() self .Show() def InitUI( self ): panel = wx.Panel( self ) panel.SetBackgroundColour( '#4f5049' ) vbox = wx.BoxSizer(wx.VERTICAL) midPan = wx.Panel(panel) midPan.SetBackgroundColour( '#ededed' ) vbox.Add(midPan, 1 , wx.EXPAND | wx. ALL , 20 ) panel.SetSizer(vbox) if __name__ = = '__main__' : app = wx.App() Example( None , title = 'Border' ) app.MainLoop() |
在上面的例子中,我们在 panel 四周设置一些空间。
1 | vbox.Add(midPan, 1 , wx.EXPAND | wx. ALL , 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
图:panel四周的边框
Go to class 程序
下面我们通过一个具体的程序详细介绍几个重点信息。
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 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | #!/usr/bin/python # -*- coding: utf-8 -*- # gotoclass.py import wx class Example(wx.Frame): def __init__( self , parent, title): super (Example, self ).__init__(parent, title = title, size = ( 390 , 350 )) self .InitUI() self .Centre() self .Show() def InitUI( self ): panel = wx.Panel( self ) 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, label = 'Class Name' ) st1.SetFont(font) hbox1.Add(st1, flag = wx.RIGHT, border = 8 ) tc = wx.TextCtrl(panel) hbox1.Add(tc, proportion = 1 ) vbox.Add(hbox1, flag = wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP, border = 10 ) vbox.Add(( - 1 , 10 )) hbox2 = wx.BoxSizer(wx.HORIZONTAL) st2 = wx.StaticText(panel, label = 'Matching Classes' ) st2.SetFont(font) hbox2.Add(st2) vbox.Add(hbox2, flag = wx.LEFT | wx.TOP, border = 10 ) vbox.Add(( - 1 , 10 )) hbox3 = wx.BoxSizer(wx.HORIZONTAL) tc2 = wx.TextCtrl(panel, style = wx.TE_MULTILINE) hbox3.Add(tc2, proportion = 1 , flag = wx.EXPAND) vbox.Add(hbox3, proportion = 1 , flag = wx.LEFT|wx.RIGHT|wx.EXPAND, border = 10 ) vbox.Add(( - 1 , 25 )) hbox4 = wx.BoxSizer(wx.HORIZONTAL) cb1 = wx.CheckBox(panel, label = 'Case Sensitive' ) cb1.SetFont(font) hbox4.Add(cb1) cb2 = wx.CheckBox(panel, label = 'Nested Classes' ) cb2.SetFont(font) hbox4.Add(cb2, flag = wx.LEFT, border = 10 ) cb3 = wx.CheckBox(panel, label = 'Non-Project classes' ) cb3.SetFont(font) hbox4.Add(cb3, flag = wx.LEFT, border = 10 ) vbox.Add(hbox4, flag = wx.LEFT, border = 10 ) vbox.Add(( - 1 , 25 )) hbox5 = wx.BoxSizer(wx.HORIZONTAL) btn1 = wx.Button(panel, label = 'Ok' , size = ( 70 , 30 )) hbox5.Add(btn1) btn2 = wx.Button(panel, label = 'Close' , size = ( 70 , 30 )) hbox5.Add(btn2, flag = wx.LEFT|wx.BOTTOM, border = 5 ) vbox.Add(hbox5, flag = wx.ALIGN_RIGHT|wx.RIGHT, border = 10 ) panel.SetSizer(vbox) if __name__ = = '__main__' : app = wx.App() Example( None , title = 'Go To Class' ) app.MainLoop() |
布局比较直观:我们创建了竖直的 sizer ,并将5个水平 sizer 放置其中。
1 2 | font = wx.SystemSettings_GetFont(wx.SYS_SYSTEM_FONT) font.SetPointSize( 9 ) |
系统默认的字体大小是10,这里显示会过大,我们将其设置为9。
1 2 3 4 | vbox.Add(hbox3, proportion = 1 , flag = wx.LEFT|wx.RIGHT|wx.EXPAND, border = 10 ) vbox.Add(( - 1 , 25 )) |
我们已经知道我们可以通过结合边框相关的 flag 参数来控制 widgets 之间的距离,但问题是Add()函数只允许设置一个边框数值,这意味着只能给几个方向一样大小的边框。如果你想左右边框设置为10px,而底部设置为25px,通过这种方法是无法做到的。如果我们需要不同的边框值,我们可以增加额外的占位空间(space)。如上面代码的vbox.Add((-1,25)),即是插入space的语句。(-1,25)分别代表宽度和长度,如果某个数值为-1则表明不关注该方向。
1 | vbox.Add(hbox5, flag = wx.ALIGN_RIGHT|wx.RIGHT, border = 10 ) |
我们在窗口的右侧放置了两个button,实现这一目标需要注意三个参数:proportion、align flag和 wx.EXPAND 标记。proportion 必须设置为0,表明在我们通过鼠标调整窗口大小时,button 不允许更改大小。一定不能设置 wx.EXPAND 标记,button 只允许出现在被分配的位置上。最后必须设置 wx.ALIGN_RIGHT 标记。水平 sizer 中的右对齐可以达到我们的目标。
图:GoToClass 窗口
wx.GridSizer
wx.GridSizer 即网格布局,它可以在两维的表格中放置 widgets。
1 | wx.GridSizer( int rows = 1 , int cols = 0 , int vgap = 0 , int hgap = 0 ) |
在上面的构造函数中,我们可以定义表格的行列数目,以及单元格之间的横竖间距。
下面的例子中,我们新建了一个计算器的骨架,对wx.GridSizer来说是一个很好的例子。
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 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | #!/usr/bin/python # -*- coding: utf-8 -*- # calculator.py import wx class Example(wx.Frame): def __init__( self , parent, title): super (Example, self ).__init__(parent, title = title, size = ( 300 , 250 )) self .InitUI() self .Centre() self .Show() def InitUI( self ): menubar = wx.MenuBar() fileMenu = wx.Menu() menubar.Append(fileMenu, '&File' ) self .SetMenuBar(menubar) vbox = wx.BoxSizer(wx.VERTICAL) self .display = wx.TextCtrl( self , style = wx.TE_RIGHT) vbox.Add( self .display, flag = wx.EXPAND|wx.TOP|wx.BOTTOM, border = 4 ) gs = wx.GridSizer( 5 , 4 , 5 , 5 ) gs.AddMany( [(wx.Button( self , label = 'Cls' ), 0 , wx.EXPAND), (wx.Button( self , label = 'Bck' ), 0 , wx.EXPAND), (wx.StaticText( self ), wx.EXPAND), (wx.Button( self , label = 'Close' ), 0 , wx.EXPAND), (wx.Button( self , label = '7' ), 0 , wx.EXPAND), (wx.Button( self , label = '8' ), 0 , wx.EXPAND), (wx.Button( self , label = '9' ), 0 , wx.EXPAND), (wx.Button( self , label = '/' ), 0 , wx.EXPAND), (wx.Button( self , label = '4' ), 0 , wx.EXPAND), (wx.Button( self , label = '5' ), 0 , wx.EXPAND), (wx.Button( self , label = '6' ), 0 , wx.EXPAND), (wx.Button( self , label = '*' ), 0 , wx.EXPAND), (wx.Button( self , label = '1' ), 0 , wx.EXPAND), (wx.Button( self , label = '2' ), 0 , wx.EXPAND), (wx.Button( self , label = '3' ), 0 , wx.EXPAND), (wx.Button( self , label = '-' ), 0 , wx.EXPAND), (wx.Button( self , label = '0' ), 0 , wx.EXPAND), (wx.Button( self , label = '.' ), 0 , wx.EXPAND), (wx.Button( self , label = '=' ), 0 , wx.EXPAND), (wx.Button( self , label = '+' ), 0 , wx.EXPAND) ]) vbox.Add(gs, proportion = 1 , flag = wx.EXPAND) self .SetSizer(vbox) if __name__ = = '__main__' : app = wx.App() Example( None , title = 'Calculator' ) app.MainLoop() |
注意下,我们在Bck和Close两个按钮之间放了一个空的wx.StaticText,来达到分隔的目的。
在例子中,我们使用了AddMany()方法,这很便于一次性插入多个widgets。 widgets是安装数组的顺序的插入到表格中的,第一行先被填充,接着是第二行,以此类推。
图:计算器
wx.FlexGridSizer
这个sizer与wx.GridSizer类似,它同样以两维的表格方式布局widgets,但wx.FlexGridSizer更灵活一些。wx.GridSizer的单元格大小都一样,wx.FlexGridSizer的单元格仅限制每行的单元格高度一致、每列的单元格宽度一致,但无需所有行列的宽高一致。
1 | wx.FlexGridSizer( int rows = 1 , int cols = 0 , int vgap = 0 , int hgap = 0 ) |
rows和cols定义了sizer的行数和列数。vgap和hgap定义了两个方向的widgets之间的间距。
很多时候,开发者需要创建Dialog对话框来接受输入和参数修改,wx.FlexGridSizer就很适合这种情况。开发者可以很容易的使用wx.FlexGridSizer来实现dialog布局。当然wx.GridSizer也可以实现,只是它不太好看,因为所有的单元格大小需要一致。
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 47 48 | #!/usr/bin/python # -*- coding: utf-8 -*- # review.py import wx class Example(wx.Frame): def __init__( self , parent, title): super (Example, self ).__init__(parent, title = title, size = ( 300 , 250 )) self .InitUI() self .Centre() self .Show() def InitUI( self ): panel = wx.Panel( self ) hbox = wx.BoxSizer(wx.HORIZONTAL) fgs = wx.FlexGridSizer( 3 , 2 , 9 , 25 ) title = wx.StaticText(panel, label = "Title" ) author = wx.StaticText(panel, label = "Author" ) review = wx.StaticText(panel, label = "Review" ) tc1 = wx.TextCtrl(panel) tc2 = wx.TextCtrl(panel) tc3 = wx.TextCtrl(panel, 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, proportion = 1 , flag = wx. ALL |wx.EXPAND, border = 15 ) panel.SetSizer(hbox) if __name__ = = '__main__' : app = wx.App() Example( None , title = 'Review' ) app.MainLoop() |
在上面的例子中我们使用FlexGridSizer创建了一个Review窗口。
1 2 3 | hbox = wx.BoxSizer(wx.HORIZONTAL) ... hbox.Add(fgs, proportion = 1 , flag = wx. ALL |wx.EXPAND, border = 15 ) |
我们创建了一个水平的sizer来在widgets表格周围放置15px的空间。
1 2 | fgs.AddMany([(title), (tc1, 1 , wx.EXPAND), (author), (tc2, 1 , wx.EXPAND), (review, 1 , wx.EXPAND), (tc3, 1 , wx.EXPAND)]) |
我们使用AddMany()添加widgets到sizer中,wx.FlexGridSizer和wx.GridSizer都有这个方法。
1 2 | fgs.AddGrowableRow( 2 , 1 ) fgs.AddGrowableCol( 1 , 1 ) |
我们让第三行和第二列为可增长的,这是的窗口变化大小时,textCtrl也会跟着增长。前两个textCtrl的宽度会增长,第三个会在两个方向都增长。记得不要忘了添加wx.EXPAND标记。
图:Review dialog 样例
wx.GridBagSizer
这是 wxPython 布局 中最复杂的sizer,很多开发者会觉得它很难使用。GridBagSizer也并非wxPython独有,其他工具包同样有。虽然它很复杂,但也不是火箭科技,还是可以掌握的:)
wx.GridBagSizer可实现精确定位,widgets还可以跨行或者跨列。构造函数如下:
1 | wx.GridBagSizer(integer vgap, integer hgap) |
竖直和水平的gap定义了所有子元素之间的空间,我们使用Add()添加元素。
1 2 | Add( self , item, tuple pos, tuple span = wx.DefaultSpan, integer flag = 0 , integer border = 0 , userData = None ) |
pos定义了位置,左上角的位置为(0,0)。span表示跨几行或者列,比如(3,2)的span表示让一个widget跨3行和2列。flag和border之前在BoxSizer中有讨论。在窗口大小改变时,grid中的widget可以保持大小不变,也可以随窗口改变。如果你想让它增长或者收缩,可以使用下面这两个方法:
1 2 | AddGrowableRow(integer row) AddGrowableCol(integer col) |
重命名窗口
在下个例子中,我们将创建一个重命名窗口。它有一个wx.StaticText,一个wx.TextCtrl和两个wx.Button。
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 | #!/usr/bin/python # -*- coding: utf-8 -*- # rename.py import wx class Example(wx.Frame): def __init__( self , parent, title): super (Example, self ).__init__(parent, title = title, size = ( 320 , 130 )) self .InitUI() self .Centre() self .Show() def InitUI( self ): panel = wx.Panel( self ) sizer = wx.GridBagSizer( 4 , 4 ) text = wx.StaticText(panel, label = "Rename To" ) sizer.Add(text, pos = ( 0 , 0 ), flag = wx.TOP|wx.LEFT|wx.BOTTOM, border = 5 ) tc = wx.TextCtrl(panel) sizer.Add(tc, pos = ( 1 , 0 ), span = ( 1 , 5 ), flag = wx.EXPAND|wx.LEFT|wx.RIGHT, border = 5 ) buttonOk = wx.Button(panel, label = "Ok" , size = ( 90 , 28 )) buttonClose = wx.Button(panel, label = "Close" , size = ( 90 , 28 )) sizer.Add(buttonOk, pos = ( 3 , 3 )) sizer.Add(buttonClose, pos = ( 3 , 4 ), flag = wx.RIGHT|wx.BOTTOM, border = 5 ) sizer.AddGrowableCol( 1 ) sizer.AddGrowableRow( 2 ) panel.SetSizerAndFit(sizer) if __name__ = = '__main__' : app = wx.App() Example( None , title = 'Rename' ) app.MainLoop() |
我们需要把这个窗口看做一个大的grid表。
1 2 | text = wx.StaticText(panel, label = "Rename To" ) sizer.Add(text, pos = ( 0 , 0 ), flag = wx.TOP|wx.LEFT|wx.BOTTOM, border = 5 ) |
“Rename To” 文本将被放置在左上角,所以我们设置了(0,0)位置。另外,我们在顶部、左边和底部增加了5px的space空间。
1 2 3 | tc = wx.TextCtrl(panel) sizer.Add(tc, pos = ( 1 , 0 ), span = ( 1 , 5 ), flag = wx.EXPAND|wx.LEFT|wx.RIGHT, border = 5 ) |
wx.TextCtrl从第二行开始,记得我们是从0开始计数的。它占据了一行和5列:(1,5)。我们放置了5px的左右边框空间。
1 2 | sizer.Add(buttonOk, pos = ( 3 , 3 )) sizer.Add(buttonClose, pos = ( 3 , 4 ), flag = wx.RIGHT|wx.BOTTOM, border = 5 ) |
我们在第四行放置了2个button。第四行是空的,所有wx.TextCtrl和button之间留有空间。我们把OK按钮放在第四列,close按钮放在第五列。需要注意,一旦我们给一个widget应用了边框,整个行都会受到影响。这是我们没有为OK设置底部边框空间的原因。仔细的读者会发现,我们在两个按钮之间没有放置任何空间,这是因为在wx.GridBagSizer的构造函数中,我们已经设置了所有widgets之间的间隔。
1 2 | sizer.AddGrowableCol( 1 ) sizer.AddGrowableRow( 2 ) |
最后需要做的是,让dialog可增长。我们让第二列和第三行可增长,现在可以放大或者缩小窗口来试试看了。你也可以注释掉这两行看看有什么效果。
图:重命名窗口
New class 样例
下个例子,我们模仿新建一个JDeveloper中的窗口,它主要用来在Java中新建类。
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 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | #!/usr/bin/python # -*- coding: utf-8 -*- # newclass.py import wx class Example(wx.Frame): def __init__( self , parent, title): super (Example, self ).__init__(parent, title = title, size = ( 450 , 350 )) self .InitUI() self .Centre() self .Show() def InitUI( self ): panel = wx.Panel( self ) sizer = wx.GridBagSizer( 5 , 5 ) text1 = wx.StaticText(panel, label = "Java Class" ) sizer.Add(text1, pos = ( 0 , 0 ), flag = wx.TOP|wx.LEFT|wx.BOTTOM, border = 15 ) icon = wx.StaticBitmap(panel, bitmap = wx.Bitmap( 'exec.png' )) sizer.Add(icon, pos = ( 0 , 4 ), flag = wx.TOP|wx.RIGHT|wx.ALIGN_RIGHT, border = 5 ) line = wx.StaticLine(panel) sizer.Add(line, pos = ( 1 , 0 ), span = ( 1 , 5 ), flag = wx.EXPAND|wx.BOTTOM, border = 10 ) text2 = wx.StaticText(panel, label = "Name" ) sizer.Add(text2, pos = ( 2 , 0 ), flag = wx.LEFT, border = 10 ) tc1 = wx.TextCtrl(panel) sizer.Add(tc1, pos = ( 2 , 1 ), span = ( 1 , 3 ), flag = wx.TOP|wx.EXPAND) text3 = wx.StaticText(panel, label = "Package" ) sizer.Add(text3, pos = ( 3 , 0 ), flag = wx.LEFT|wx.TOP, border = 10 ) tc2 = wx.TextCtrl(panel) sizer.Add(tc2, pos = ( 3 , 1 ), span = ( 1 , 3 ), flag = wx.TOP|wx.EXPAND, border = 5 ) button1 = wx.Button(panel, label = "Browse..." ) sizer.Add(button1, pos = ( 3 , 4 ), flag = wx.TOP|wx.RIGHT, border = 5 ) text4 = wx.StaticText(panel, label = "Extends" ) sizer.Add(text4, pos = ( 4 , 0 ), flag = wx.TOP|wx.LEFT, border = 10 ) combo = wx.ComboBox(panel) sizer.Add(combo, pos = ( 4 , 1 ), span = ( 1 , 3 ), flag = wx.TOP|wx.EXPAND, border = 5 ) button2 = wx.Button(panel, label = "Browse..." ) sizer.Add(button2, pos = ( 4 , 4 ), flag = wx.TOP|wx.RIGHT, border = 5 ) sb = wx.StaticBox(panel, label = "Optional Attributes" ) boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL) boxsizer.Add(wx.CheckBox(panel, label = "Public" ), flag = wx.LEFT|wx.TOP, border = 5 ) boxsizer.Add(wx.CheckBox(panel, label = "Generate Default Constructor" ), flag = wx.LEFT, border = 5 ) boxsizer.Add(wx.CheckBox(panel, label = "Generate Main Method" ), flag = wx.LEFT|wx.BOTTOM, border = 5 ) sizer.Add(boxsizer, pos = ( 5 , 0 ), span = ( 1 , 5 ), flag = wx.EXPAND|wx.TOP|wx.LEFT|wx.RIGHT , border = 10 ) button3 = wx.Button(panel, label = 'Help' ) sizer.Add(button3, pos = ( 7 , 0 ), flag = wx.LEFT, border = 10 ) button4 = wx.Button(panel, label = "Ok" ) sizer.Add(button4, pos = ( 7 , 3 )) button5 = wx.Button(panel, label = "Cancel" ) sizer.Add(button5, pos = ( 7 , 4 ), span = ( 1 , 1 ), flag = wx.BOTTOM|wx.RIGHT, border = 5 ) sizer.AddGrowableCol( 2 ) panel.SetSizer(sizer) if __name__ = = '__main__' : app = wx.App() Example( None , title = "Create Java Class" ) app.MainLoop() |
这是一个更复杂的布局,我们同时使用了wx.GridBagSizer和wx.StaticBoxSizer。
1 2 3 | line = wx.StaticLine(panel) sizer.Add(line, pos = ( 1 , 0 ), span = ( 1 , 5 ), flag = wx.EXPAND|wx.BOTTOM, border = 10 ) |
上面的代码创建了一条分隔线,来分隔布局中不同组的widgets。
1 2 3 | icon = wx.StaticBitmap(panel, bitmap = wx.Bitmap( 'exec.png' )) sizer.Add(icon, pos = ( 0 , 4 ), flag = wx.TOP|wx.RIGHT|wx.ALIGN_RIGHT, border = 5 ) |
我们在第一行右侧放了一个wx.StaticBitmap。
1 2 | sb = wx.StaticBox(panel, label = 'Optional Attributes' ) boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL) |
wxStaticBoxSizer和wx.BoxSizer类似,但它在sizer周围添加了一个静态的盒子,我们在盒子中放入了check选项。
图:New class窗口
这一节教程主要讲 wxpython 布局 与 布局管理。