在wxPython中提供多种网格布局 wx.GridSizer,wx.FlexGridSizer和wx.GridBagSizer, 它们都提供在一个二维表格中进行布局的功能。在wx.GridSizer布局中,表格中的每个单元格都具有相同的尺寸,而wx.FlexGridSizer则具有更灵活的布局。Wx.GirdBagSizer则在wx.FlexGridSizer之上提供了更多的增强功能。
一、wx.GridSizer
wx.GridSizer提供基本的网格布局功能,其继承关系如图1所示:
图1:wx.GridSizer继承关系图
GridSizer构造函数如下:
wx.GridSizer(rows, columns, vgap, hgap):
参数:rows定义GridSizer的行数;
cols 定义GridSizer的列数;
vgap 定义垂直方向上行间距;
hgap 定义水平方向上列间距。
wx.GridSizer常用函数有:
- Add() 在网格中添加一个控件;
- AddMany() 在网格中添加多个控件;
- SetRows() 设置Sizer的行数;
- GetRows() 获得Sizer的行数;
- SetCols() 设置Sizer的列数;
- GetCols() 获得Sizer的列数;
- SetVCap() 设置单元格之间的垂直间隔(像素);
- GetVCap() 获得单元格自建的垂直间隔;
- SetHCap() 设置单元格之间的水平间隔(像素);
- GetHCap() 获得单元格自建的水平间隔。
二、wx.GridSizer示例
下面的代码演示了使用wx.GrideSizer的AddMany()方法构建一个简单的计算器界面,可以看出,其中的控件按行依次填充,首先填满第一列,然后第二列,依次类推。完整代码如下:
import wx
#使用wx.GridSizer实现一个简单的网格布局
class Example(wx.Frame):
def __init__(self, *args, **kwargs):
super(Example, self).__init__(*args, **kwargs)
self.SetTitle('实战wxPython: 计算器')
self.SetSize(400, 300)
self.InitUi()
self.Centre()
def InitUi(self):
#设置应用退出菜单
menubar = wx.MenuBar()
fileMenu = wx.Menu()
miExit = wx.MenuItem(fileMenu, wx.ID_EXIT, '退出(&Q)\tCtrl+Q')
fileMenu.Append(miExit)
#绑定菜单项的行为
self.Bind(wx.EVT_MENU, self.OnQuit, miExit)
menubar.Append(fileMenu, '文件(&F)')
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)
def OnQuit(self, e):
self.Close()
def main():
app = wx.App()
window = Example(None)
window.Show()
app.MainLoop()
if __name__ == '__main__':
main()
上述代码的运行结果如图2所示:
图2:GridSizer布局演示
三、wx.FlexGridSizer
wx.FlexGridSizer继承自wx.GriderSizer,它提供了比wx.GridSizer更灵活的网格布局方法,除与wx.GridSizer相同功能之外,还增加以下一些功能 :
- 每行和每列可以有各自的尺寸;
- 在默认情况下,对尺寸大小进行调节时,会改变行和列的整体尺寸,在FlexGriderSizer中,可以指定某行或者某列的尺寸进行调节;
- 可以在行和列两个方向进行灵活调整,可以为指定个别子元素指定比列量,并且可以指定固定方向上的调整行为。
wx.FlexGridSizer的常用函数有:
- AddGrowableCol(idx, proportion=0) 设定索引为idx的列为可增长列;
- AddGrowableRow(idx, proportion=0) 设定索引为idx的行为可增长行。
参数:proportion=0 为默认,表示所有的可增长行或列 按照同比列缩放。如果要指定不一样的缩放比例,那么需要手动设置proportion 值。例如,如 果你有两个尺寸可调整的行,并且它们的proportion分别是2和1,那么这第一个行将得到新空间的2/3,第二行将得到 1/3。
wx.FlexGridSizer的继承关系如图3所示:
图3:wx.FlexGridSizer继承关系图
四、 wx.FlexGridSizer示例
下面的代码演示了如何使用FlexGridSizer来进行布局:
# 演示wx.FlexGridSizer布局
import wx
class SampleFlexGridSizer(wx.Frame):
def __init__(self, parent, title):
super(SampleFlexGridSizer, self).__init__(parent, title=title)
self.InitUi()
self.Centre()
def InitUi(self):
panel = wx.Panel(self)
hBox = wx.BoxSizer(wx.HORIZONTAL)
fgs = wx.FlexGridSizer(3, 2, 9, 25)
title = wx.StaticText(panel, label="标题")
author = wx.StaticText(panel, label="作者")
review = wx.StaticText(panel, label="评审")
tcTitle = wx.TextCtrl(panel)
tcAuthor = wx.TextCtrl(panel)
tcReview = wx.TextCtrl(panel, style=wx.TE_MULTILINE)
fgs.AddMany([(title), (tcTitle, 1, wx.EXPAND),
(author), (tcAuthor, 1, wx.EXPAND),
(review, 1, wx.EXPAND), (tcReview, 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)
def main():
app = wx.App()
sample = SampleFlexGridSizer(None,"实战wxPython: FlexGridSizer演示")
sample.Show()
app.MainLoop()
if __name__ == "__main__":
main()
在代码中,我们加入了以下两句:
fgs.AddGrowableRow(2,1)
fgs.AddGrowableCol(1,1)
它们将控制第三行和第二列根据窗口的调整其尺寸做相应调整.在上述界面中,前面两列的文本编辑框沿水平方向扩张,而第三列的文本框则同时沿水平和垂直方向进行扩展。注意,为了达到上述扩展效果,我们需要指定相应控件的为扩展的(设置相应标记为wx.EXPAND)。
上述示例的最终运行效果如图4所示:
图4:FlexGridSizer布局演示
五、wx.GridBagSizer
在wxPython中还提供了一种更灵活的网格布局方式wx.GridBagSizer, wx.GridBagSizer显式支持在指定的网格位置添加一个控件,同时也可以指定控件跨越行或者列。因此它可以更灵活地实现更复杂的布局效果。wx.GridBagSizer的继承关系如图5所示:
图5:wx.GridBagSizer继承关系图
wx.GridBagSizer常用方法:
- Add(): 在网格指定位置处添加一个控件;
- GetItemPosition(): 返回指定位置的控件项;
- SetItemPosition(): 在网格指定位置放置一个控件项;
- GetItemSpan(): 返回一个控件项的行/列跨越数;
- SetItemSpan(): 设置一个控件项的行/列跨越数。
六、wx.GridBagSizer示例
下面的代码演示了如何使用wx.GridBagSizer实现一个相对复杂的布局:
# 演示wx.GridBagSizer布局
import os
import wx
class SampleGridBagSizer(wx.Frame):
def __init__(self, parent, title):
super(SampleGridBagSizer, self).__init__(parent, title=title)
self.InitUi()
self.Centre()
def InitUi(self):
panel = wx.Panel(self)
# GridBagSizer作为panel的主布局
sizer = wx.GridBagSizer(5, 5)
labelJavaClass = wx.StaticText(panel, label="Java类") # Java class
sizer.Add(labelJavaClass, pos=(0, 0), flag=wx.TOP|wx.LEFT|wx.BOTTOM, border=15)
imgPath = os.path.dirname(__file__) #图片文件的绝对路径
icon = wx.StaticBitmap(panel, bitmap=wx.Bitmap(imgPath + "/python-logo.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)
labelName = wx.StaticText(panel, label="名称") # Name
sizer.Add(labelName, pos=(2, 0), flag=wx.LEFT, border=10)
tcName = wx.TextCtrl(panel)
sizer.Add(tcName, pos=(2, 1), span=(1, 3), flag=wx.TOP|wx.EXPAND)
labelPackage = wx.StaticText(panel, label="包") # Package
sizer.Add(labelPackage, pos=(3, 0), flag=wx.LEFT|wx.TOP, border=10)
tcPackage = wx.TextCtrl(panel)
sizer.Add(tcPackage, pos=(3, 1), span=(1, 3), flag=wx.TOP|wx.EXPAND, border=5)
buttonBrowse1 = wx.Button(panel, label="浏览...") # Browse...
sizer.Add(buttonBrowse1, pos=(3, 4), flag=wx.TOP|wx.RIGHT, border=5)
labelExtends = wx.StaticText(panel, label="扩展") # Extends
sizer.Add(labelExtends, pos=(4, 0), flag=wx.TOP|wx.LEFT, border=10)
comboExtends = wx.ComboBox(panel)
sizer.Add(comboExtends, pos=(4, 1), span=(1, 3), flag=wx.Top|wx.EXPAND, border=5)
buttonBrowse2 = wx.Button(panel, label="浏览...") # Browse...
sizer.Add(buttonBrowse2, pos=(4, 4), flag=wx.TOP|wx.RIGHT, border=5)
sbOptAttr = wx.StaticBox(panel, label="可选属性") # Optional Attributes
# 垂直布局
vboxSizer = wx.StaticBoxSizer(sbOptAttr, wx.VERTICAL)
chkPublic = wx.CheckBox(panel, label="公共") # Public
vboxSizer.Add(chkPublic, flag=wx.LEFT|wx.TOP, border=5)
chkGeneDefConstructor = wx.CheckBox(panel, label="创建缺省构造函数") # Generate Default Constructor
vboxSizer.Add(chkGeneDefConstructor, flag=wx.LEFT, border=5)
chkGeneMainMethod = wx.CheckBox(panel, label="创建Main方法")
vboxSizer.Add(chkGeneMainMethod, flag=wx.LEFT|wx.BOTTOM, border=5)
sizer.Add(vboxSizer, pos=(5, 0), span=(1,5), flag=wx.EXPAND|wx.TOP|wx.LEFT|wx.RIGHT, border=10)
buttonHelp = wx.Button(panel, label="帮助") # Help
sizer.Add(buttonHelp, pos=(7, 0), flag=wx.LEFT, border=10)
buttonOK = wx.Button(panel, label="确定") # OK
sizer.Add(buttonOK, pos=(7, 3))
buttonCancel = wx.Button(panel, label="取消")
sizer.Add(buttonCancel, pos=(7, 4), span=(1, 1), flag=wx.BOTTOM|wx.RIGHT, border=10)
sizer.AddGrowableCol(2)
panel.SetSizer(sizer)
sizer.Fit(self)
def main():
app = wx.App()
sample = SampleGridBagSizer(None, title="实战wxPython: 网格布局演示-创建JAVA类")
sample.Show()
app.MainLoop()
if __name__ == '__main__':
main()
其运行效果如图6所示:
图6:wx.GridBagSizer布局演示
七、本文知识点
- 网格布局的基本使用方法;
- 了解和使用GridSizer;
- 了解和使用FlexGridSizer;
- 了解和使用GridBagSizer。