使用绝对布局会有以下问题:
1.子窗口(或控件)位置和大小不会随着父窗口的变化而变化
2.在不同平台上显示效果可能差别很大
3.在不同分辨率下显示效果可能差别很大
4.字体的变化也会对显示效果有影响
5.动态添加或删除子窗口(或控件)界面布局需要重新设计
wxPython提供了8个布局管理器类:
创建wx.BoxSizer对象时可以指定布局方向:
hbox = wx.BoxSizer(wx.HORIZONTAL)#设置为水平方向布局
hbox = wx.BoxSizer() #也是设置为水平方向布局,wx.HORIZONTAL为默认值可以省略
vhbox = wx.BoxSizer(wx.VERTICAL)#设置为垂直方向布局
当需要添加子窗口(或控件)到父窗口时,需要调用wx.BoxSizer对象的Add()方法
Add()方法是从父类wx.Sizer继承而来
Add()方法语法说明如下:
Add(window,proportion=0,flag=0,border=0,userData=None)#添加到父窗口
Add(sizer,proportion=0,flag=0,border=0,userData=None)#添加到另外一个Sizer(布局管理器)中,用于嵌套
Add(width,height,proportion=0,flag=0,border=0,userData=None)#添加一个空白空间
proportion:权重,仅被wx.BoxSizer使用,设置当前子窗口(或控件)在父窗口所占空间比例
flag:用来控制对齐、边框和调整尺寸
border:边框的宽度,一个空白空间
userData:用来传递额外的数据
flag标志:
例:完成下图布局(垂直布局中嵌套水平布局)
#Box布局器
'''使用步骤:
1.创建BoxSizer对象
2.将控件添加到布局管理器中,由布局管理器管理控件布局(但布局管理器不是一个容器)
本例中
1.创建一个垂直方向的box布局管理器-vbox
2.写一个静态文本框,并将其添加到vbox
3.创建一个水平方向的box布局管理器-hbox
4.写两个button,并将button添加到hbox
5.将hbox添加到vbox中
6.将vbox添加到这个面板中
'''
import wx
#自定义窗口类MyFrame
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None,title="Box布局器",size=(300,120))
self.Centre()#设置窗口居中
panel = wx.Panel(parent=self)
#创建垂直方向box布局管理器
vbox=wx.BoxSizer(wx.VERTICAL)
#创建一个静态文本
self.statictext = wx.StaticText(parent=panel,label='Button1单击')
#添加静态文本到vbox布局管理器中,指定文本框在整个面板中所占权重为2,标志为固定大小填充,顶部有边框,水平居中,边框宽度为10
vbox.Add(self.statictext,proportion=2,flag=wx.FIXED_MINSIZE | wx.TOP | wx.CENTER,border=10)
#设置两个button按钮并绑定点击事件
b1=wx.Button(parent=panel,id=10,label='button1')
b2=wx.Button(parent=panel,id=11,label='button2')
self.Bind(wx.EVT_BUTTON,self.on_click,id=10,id2=20)
#创建水平方向box布局管理器(默认水平方向)
hbox = wx.BoxSizer()
#将两个button添加到hbox布局管理器中
hbox.Add(b1,0,wx.EXPAND | wx.BOTTOM ,border=5)
hbox.Add(b2,0,wx.EXPAND | wx.BOTTOM ,border=5)
#将hbox添加到vbox
vbox.Add(hbox,proportion=1,flag=wx.CENTER)
#整个界面为一个面板,面板中设置一个垂直方向的布局管理器(根布局管理器)
panel.SetSizer(vbox)
'''将两个button放到一个水平方向布局管理器,然后将水平方向布局管理器放到垂直方向布局管理器中
添加控件到其父容器是通过parent属性,这里button和statictext的父容器都是面板,与布局管理器的添加是没有关系的
布局管理器添加是通过Add()方法添加,这个添加只是说将某个控件纳入布局管理器管理
不是添加到容器中,注意布局管理器不是一个容器'''
def on_click(self):
pass
#自定义应用程序对象
class App(wx.App):
def OnInit(self):
#创建窗口对象
frame = MyFrame()
frame.Show()
return True
def OnExit(self):
print('应用程序退出')
return 0
if __name__ == '__main__':
app = App()#调用上面函数
app.MainLoop()#进入主事件循环
wx.StaticBoxSizer构造方法如下:
1.wx.StaticBoxSizer(box,orient=HORIZONTAL)
box参数:wx.StaticBox(静态框)对象
orient参数:布局方向
2.wx.StaticBoxSizer(orient,parent,label="")
orient参数:布局方向
parent参数:设置所在的父窗口
label参数:设置边框的静态文本
例:如图
步骤:
1.创建一个垂直方向的box布局管理器-vbox
2.写一个静态文本框,并将其添加到vbox
3.创建一个静态框,指定其父容器和label
4.创建水平方向staticbox布局管理器-hsbox,传入静态框对象和布局方向
5.写两个button,并将button添加到hsbox
6.将hsbox添加到vbox中
7.将vbox添加到这个面板中
import wx
#自定义窗口类MyFrame
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None,title="Box布局器",size=(300,120))
self.Centre()#设置窗口居中
panel = wx.Panel(parent=self)
#创建垂直方向box布局管理器
vbox=wx.BoxSizer(wx.VERTICAL)
self.statictext = wx.StaticText(parent=panel,label='Button1单击')
vbox.Add(self.statictext,proportion=2,flag=wx.FIXED_MINSIZE | wx.TOP | wx.CENTER,border=10)
b1=wx.Button(parent=panel,id=10,label='button1')
b2=wx.Button(parent=panel,id=11,label='button2')
self.Bind(wx.EVT_BUTTON,self.on_click,id=10,id2=20)
#c创建一个静态框
sb = wx.StaticBox(parent=panel,label='按钮框')
#创建水平方向staticbox布局管理器
hsbox = wx.StaticBoxSizer(sb,wx.HORIZONTAL)
hsbox.Add(b1,0,wx.EXPAND | wx.BOTTOM ,border=5)
hsbox.Add(b2,0,wx.EXPAND | wx.BOTTOM ,border=5)
vbox.Add(hsbox,proportion=1,flag=wx.CENTER)
panel.SetSizer(vbox)
def on_click(self):
pass
#自定义应用程序对象
class App(wx.App):
def OnInit(self):
#创建窗口对象
frame = MyFrame()
frame.Show()
return True
def OnExit(self):
print('应用程序退出')
return 0
if __name__ == '__main__':
app = App()#调用上面函数
app.MainLoop()#进入主事件循环
Grid布局类wx.GridSizer,Grid布局以网格形式对子窗口(或控件)进行摆放,容器被分成大小相等的矩形,一个矩形中放置一个子窗口(或控件)。
wx.GridSizer的构造方法如下:
(1)wx.GridSizer(rows,cols,vgap,hgap)
创建指定行数和列数的wx.GridSizer对象,并指定水平和垂直间隙,参数hgap为水平间隙,参数vgap为垂直间隙,整数类型。添加的子窗口(或控件)个数超过rows*cols之积,则引发异常。
(2)wx.GridSizer(rows,cols,gap)
同wx.GridSizer(rows,cols,vgap,hgap),gap参数指定垂直间隙和水平间隙,gap参数是wx.Size类型
例如wx.Size(2,3)是设置水平间隙为2像素,垂直间隙为3像素
(3)wx.GridSizer(cols,vgap,hgap)
创建指定列数的wx.GridSizer对象,并指定水平和垂直间隙。由于没有限定行数,所以添加的子窗口(或控件)个数没有限制
(4)wx.GridSizer(cols,gap=wx.Size(0,0))
同wx.GridSizer(cols,vgap,hgap),gap参数是垂直间隙和水平间隙是wx.Size类型
例:如图
import wx
#自定义窗口类MyFrame
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None,title="Grid布局器",size=(300,300))
self.Centre()#设置窗口居中
panel = wx.Panel(parent=self)
#创建9个按钮,3*3布局
btn1 = wx.Button(parent=panel,label='1')
btn2 = wx.Button(parent=panel,label='2')
btn3 = wx.Button(parent=panel,label='3')
btn4 = wx.Button(parent=panel,label='4')
btn5 = wx.Button(parent=panel,label='5')
btn6 = wx.Button(parent=panel,label='6')
btn7 = wx.Button(parent=panel,label='7')
btn8 = wx.Button(parent=panel,label='8')
btn9 = wx.Button(parent=panel,label='9')
'''
#创建Grid布局管理器,将按钮添加进grid布局管理器中
gridsizer = wx.GridSizer(cols=3,rows=3,gap=wx.Size(5,10))
gridsizer.Add(btn1,0,wx.EXPAND)
gridsizer.Add(btn2,0,wx.EXPAND)
gridsizer.Add(btn3,0,wx.EXPAND)
gridsizer.Add(btn4,0,wx.EXPAND)
gridsizer.Add(btn5,0,wx.EXPAND)
gridsizer.Add(btn6,0,wx.EXPAND)
gridsizer.Add(btn7,0,wx.EXPAND)
gridsizer.Add(btn8,0,wx.EXPAND)
gridsizer.Add(btn9,0,wx.EXPAND)
等同于下面
'''
#创建Grid布局管理器,将按钮添加进grid布局管理器中,最多添加9个控件,只能少不能多
gridsizer = wx.GridSizer(cols=3,rows=3,gap=wx.Size(5,10))
gridsizer.AddMany([
(btn1,0,wx.EXPAND),
(btn2,0,wx.EXPAND),
(btn3,0,wx.EXPAND),
(btn4,0,wx.EXPAND),
(btn5,0,wx.EXPAND),
(btn6,0,wx.EXPAND),
(btn7,0,wx.EXPAND),
(btn8,0,wx.EXPAND),
(btn9,0,wx.EXPAND)
])
#将Grid布局管理器添加进控制面板中
panel.SetSizer(gridsizer)
#自定义应用程序对象
class App(wx.App):
def OnInit(self):
#创建窗口对象
frame = MyFrame()
frame.Show()
return True
def OnExit(self):
print('应用程序退出')
return 0
if __name__ == '__main__':
app = App()#调用上面函数
app.MainLoop()#进入主事件循环
Grid布局时网格大小是固定的,如果想网格大小不同的界面可以使用FlexGrid布局。
FlexGrid是更加灵活的Grid布局。FlexGrid布局类是wx.FlexGridSizer,它的父类是wx.GridSizer。
FlexGridSizer构造方法同GridSizer
wx.FlexGridSizer有两个特殊的方法:
(1)AddGrowableRow(idx,proportion=0)
指定行是可以扩展的,参数idx是行索引,从零开始;参数proportion是设置该行所占空间比例
(2)AddGrowableCo(idx,proportion=0)
指定列是可以扩展的,参数idx是列索引,从零开始;参数proportion是设置该列所占空间比例
例:如图
import wx
#自定义窗口类MyFrame
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None,title="FlexGrid布局器",size=(400,200))
self.Centre()#设置窗口居中
panel = wx.Panel(parent=self)
#创建FlexGrid布局管理器
fgs = wx.FlexGridSizer(3,2,10,10)
#静态文本
title = wx.StaticText(panel,label='标题:')
author = wx.StaticText(panel,label='作者:')
review = wx.StaticText(panel,label='内容:')
#文本框控件
tcl = wx.TextCtrl(panel)
tc2 = wx.TextCtrl(panel)
tc3 = wx.TextCtrl(panel,style=wx.TE_MULTILINE)
fgs.AddMany([
title,(tcl,1,wx.EXPAND),
author,(tc2,1,wx.EXPAND),
review,(tc3,1,wx.EXPAND)
])
#指定行,(行索引,行所占空间比例)
fgs.AddGrowableRow(0,1)#高度占1/5
fgs.AddGrowableRow(1,1)#占1/5
fgs.AddGrowableRow(2,3)#占3/5
#指定列,(列索引,列所占空间比例)
fgs.AddGrowableCol(0,1)
fgs.AddGrowableCol(1,2)
#将FlexGrid布局管理器添加进面板
panel.SetSizer(fgs)
#自定义应用程序对象
class App(wx.App):
def OnInit(self):
#创建窗口对象
frame = MyFrame()
frame.Show()
return True
def OnExit(self):
print('应用程序退出')
return 0
if __name__ == '__main__':
app = App()#调用上面函数
app.MainLoop()#进入主事件循环
如图:
import wx
#自定义窗口类MyFrame
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None,title="FlexGrid布局器",size=(400,200))
self.Centre()#设置窗口居中
panel = wx.Panel(parent=self)
#创建FlexGrid布局管理器(行数,列数,行间隙,列间隙)
fgs = wx.FlexGridSizer(3,2,10,10)
title = wx.StaticText(panel,label='标题:')
author = wx.StaticText(panel,label='作者:')
review = wx.StaticText(panel,label='内容:')
tcl = wx.TextCtrl(panel)
tc2 = wx.TextCtrl(panel)
tc3 = wx.TextCtrl(panel,style=wx.TE_MULTILINE)#文本内容框,多行
fgs.AddMany([
title,(tcl,1,wx.EXPAND),
author,(tc2,1,wx.EXPAND),
review,(tc3,1,wx.EXPAND)
])
fgs.AddGrowableRow(0,1)#高度占1/5
fgs.AddGrowableRow(1,1)#占1/5
fgs.AddGrowableRow(2,3)#占3/5
fgs.AddGrowableCol(0,1)
fgs.AddGrowableCol(1,2)
#为在整个flaxgridsizer外留出空白,则在FlexGridSizer外嵌套一个BoxSizer,为BoxSizer设置flag属性
hbox = wx.BoxSizer()
hbox.Add(fgs,proportion=1,flag=wx.ALL | wx.EXPAND,border=20)
panel.SetSizer(hbox)
#自定义应用程序对象
class App(wx.App):
def OnInit(self):
#创建窗口对象
frame = MyFrame()
frame.Show()
return True
def OnExit(self):
print('应用程序退出')
return 0
if __name__ == '__main__':
app = App()#调用上面函数
app.MainLoop()#进入主事件循环
为在整个flaxgridsizer外留出空白,则在FlexGridSizer外嵌套一个BoxSizer,为BoxSizer设置flag属性