布局管理

使用绝对布局会有以下问题:
1.子窗口(或控件)位置和大小不会随着父窗口的变化而变化
2.在不同平台上显示效果可能差别很大
3.在不同分辨率下显示效果可能差别很大
4.字体的变化也会对显示效果有影响
5.动态添加或删除子窗口(或控件)界面布局需要重新设计

wxPython提供了8个布局管理器类:

wxpython界面模板 wxpython 布局_App

1.Box布局管理器(默认水平布局)

创建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标志:

wxpython界面模板 wxpython 布局_布局管理器_02

wxpython界面模板 wxpython 布局_wxpython界面模板_03

wxpython界面模板 wxpython 布局_布局管理器_04

 

例:完成下图布局(垂直布局中嵌套水平布局)

wxpython界面模板 wxpython 布局_App_05

wxpython界面模板 wxpython 布局_布局管理器_06


 

#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()#进入主事件循环

 

2.StaticBox布局

wx.StaticBoxSizer构造方法如下:
    1.wx.StaticBoxSizer(box,orient=HORIZONTAL)
    box参数:wx.StaticBox(静态框)对象
    orient参数:布局方向
    
    2.wx.StaticBoxSizer(orient,parent,label="")
    orient参数:布局方向
    parent参数:设置所在的父窗口
    label参数:设置边框的静态文本

例:如图

wxpython界面模板 wxpython 布局_控件_07

步骤:

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()#进入主事件循环

 

3.Grid布局

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类型
 

例:如图

wxpython界面模板 wxpython 布局_App_08

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()#进入主事件循环

 

4.FlexGrid布局

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是设置该列所占空间比例

例:如图

wxpython界面模板 wxpython 布局_App_09

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()#进入主事件循环

如图:

wxpython界面模板 wxpython 布局_控件_10

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属性