wxPython 实践(三)页面布局

wxPython 实践(一)概述
wxPython 实践(二)基础控件
wxPython 实践(三)页面布局
wxPython 实践(四)事件响应
wxPython 实践(五)高级控件
wxPython 实践(六)对话框
wxPython 实践(七)GDI 介绍
wxPython 实践(八)其他


官网
https://docs.wxpython.org/wx.1moduleindex.html
https://www.w3ccoo.com/wxpython/wxpython_major_classes.html
系列文章:
https://wintel.blog.csdn.net/?type=blog

1. 界面布局基础

一个典型的 GUI 程序的窗口界面中,一般是由各种控件(或者部件)组成,这些部件一般都会按一定的布局呈现在窗口中。布局方式可以分为绝对定位布局和相对定位布局,绝对定位布局中的控件不会随窗口的大小变化而做调整,相对布局则会根据窗口的尺寸对其中的控件布局进行调整,以更好地适应窗口的变化。
在比较久远的一些 GUI 框架中,一般只支持绝对定位布局,比如微软的 MFC 框架,只支持绝对定位布局。绝对布局虽然使用方便,但有很大的局限性。一般现代 GUI 框架,无论是微软的 .Net 框架,Andriod SDK 里的布局,wxWidgets, Qt 等 C++ 框架,都提供了布局管理功能,来提供更灵活的窗口布局。
PyQt5 是 QT5 的 Python 封装,wxPython 是 wxWidgets 的 Python 封装,因此你无论是在 PyQt5 还是在 wxPython 中,都提供了管理应用程序布局的功能模块。在 wxPython 中,可以使用绝对定位或者使用 sizer 来进行布局管理。

2. 绝对定位布局

绝对布局是指在窗口中以像素为单位指定每个部件的位置和大小。
绝对定位布局有几个明显的缺点:

  • 如果我们调整窗口大小,部件的大小和位置不会改变。
  • 在不同平台上,应用程序看起来都不同。
  • 在应用程序中更改字体可能会破坏布局。
  • 如果决定更改布局,则必须完全重做布局,这样做既繁琐又耗时,更容易出错。

在一些简单的测试程序,使用绝对布局可以快速演示某个功能,但是在大多数情况下,都使用 sizer 来进行布局管理。

import wx
 
class MyWin(wx.Frame):
    def __init__(self, parent, title):
        # super(MyWin, self).__init__(parent, title)
        super().__init__(parent, title = title) 
        self.SetTitle(title=title)
        # self.SetSize(480, 360)
        panel = wx.Panel(self)
        # panel.SetBackgroundColour("gray")

        self.python = wx.StaticText(panel, -1, style=wx.ALIGN_CENTER)
        self.python.SetLabel("python")
        self.python.SetPosition((10, 10))
        
        self.cplus = wx.StaticText(panel, -1, style=wx.ALIGN_CENTER)
        self.cplus.SetLabel("cplus")
        self.cplus.SetPosition((100, 10))

        self.java = wx.StaticText(panel, -1, style=wx.ALIGN_CENTER)
        self.java.SetLabel("java")
        self.java.SetPosition((20, 150))
        
        self.Centre()     
        
if __name__ == '__main__':
    app = wx.App()
    window = MyWin(None, title="Absolute Position")
    window.Show()
    app.MainLoop()

在这里插入图片描述
参考:
https://wintel.blog.csdn.net/article/details/130787339?spm=1001.2014.3001.5502
https://wintel.blog.csdn.net/article/details/130787364?spm=1001.2014.3001.5502

3. 相对定位布局

用户界面的布局是指如何在窗口或面板中组织和排列各个控件。
在 wxPython 中,布局管理器(sizers)用于自动处理这些控件的布局。布局管理器可以响应窗口大小的变化并重新定位或调整控件的大小,从而实现动态的界面布局。
wxPython 提供了多种布局管理器,每种都有其特定的用途和特点。

  • wx.BoxSizer : 按水平或垂直方向排列子控件,是使用最广泛的布局管理器。
  • wx.GridSizer : 将控件排列成网格形式。
  • wx.FlexGridSizer : 与 wx.GridSizer 类似,但提供了更灵活的行和列大小设置。
  • wx.StaticBoxSizer : 在一个静态框内组织控件,同时具有边框和标题
  • wx.GridBagSizer:

3.1. 盒式布局管理器(wx.BoxSizer)

盒式布局(Box Layout)是一种使用最为广泛的布局管理器。它将容器内的控件顺序排列成一行或一列,就像在一个盒子里放置物品一样。
这种方式非常适合创建垂直或水平的工具栏、状态栏,或者是一个选项卡控件内的页面。
参考:https://www.w3ccoo.com/wxpython/wx_boxsizer.html

3.1.1. 类定义

  • AddSpacer(self, size): 在调整器的主方向上添加不可拉伸空间,更可读的调用方式如下:
If boxSizer.IsVertical():
      boxSizer.Add(0, size, 0)
else:
      boxSizer.Add(size, 0, 0)
  • CalcMin(self): 提供计算 boxSizer 最小值的方法, 它只在内部使用,用户不能调用它。
  • GetOrientation(self): 返回 boxSizer 的布局方向,其返回值为 wx.VERTICAL 或wx.HORIZONTAL。
  • SetOrientation(self, orient): 设置 boxSizer 的方向, 参数 orient 的取值为wx.VERTICAL 或 wx.HORIZONTAL。
  • RepositionChildren(self, minSize): 通过最近一次调用 CalcMin 方法和 sizer 当前可用的总尺寸(m_size)来重新提供 boxSizer 中子控件的位置。在导出类中,该方法必须重载。
  • Add(window : wx.Window, proportion=0 : interger, flag=0 : interger, border = 0 :interger): 它向Sizer添加一个子控件。
    参数 orient 的取值可以为 wx.VERTICAL 或 wx.HORIZONTAL。
    参数 proportion 定义小部件在定义方向上变化的比例。假设我们有三个比例为 0、1 和2 的按钮。它们被添加到水平的 wx.BoxSizer 中。比例为0的按钮不会改变,比例为2的按钮在水平长度是比例为1的按钮长度的两倍。
    参数 flag, 可以进一步配置 wx.BoxSizer 中小部件的行为, flag 可以使用以下参数和这这些参数的组合:
    wx.LEFT
    wx.RIGHT
    wx.BOTTOM
    wx.TOP
    wx.ALL
    参数 border 则可以调整 BoxSizer 内部子控件之间的距离。

3.1.2. 实例

一个简单的布局管理器使用示例如下:

import wx
 
class MyWin(wx.Frame):
    def __init__(self, parent, title):
        # super(MyWin, self).__init__(parent, title)
        super().__init__(parent, title = title) 
        self.SetTitle(title=title)
        panel = wx.Panel(self)
        # 初始化垂直布局
        box_sizer = wx.BoxSizer(wx.VERTICAL)

        # 布局中添加三个控件
        text = wx.StaticText(panel, label="Text Label")
        button1 = wx.Button(panel, label="Button 1")
        button2 = wx.Button(panel, label="Button 2")
        box_sizer.Add(text, flag=wx.LEFT|wx.TOP, border=10)
        box_sizer.Add(button1, proportion=1, flag=wx.EXPAND|wx.ALL, border=10)
        box_sizer.Add(button2, proportion=1, flag=wx.EXPAND|wx.ALL, border=10)

        # 面板中添加布局
        panel.SetSizer(box_sizer)
        self.Show()
        
if __name__ == '__main__':
    app = wx.App()
    window = MyWin(None, title="BoxSizer")
    window.Show()
    app.MainLoop()

在这个例子中,我们使用了一个垂直方向的 wx.BoxSizer 来组织一个静态文本控件和两个按钮。 proportion 参数设置了控件在可用空间中占据的比例,而 flag 参数和 border 参数用于定义控件与其它控件或边界之间的边距。
在这里插入图片描述

3.2. 静态盒式布局器(wx.StaticBoxSizer)

https://www.w3ccoo.com/wxpython/wx_staticboxsizer.html

3.2.1. 类定义

wx.StaticBoxSizer继承自wx.BoxSizer。
wx.StaticBoxSizer 将盒子大小调整器放入静态盒子中。 它在盒子周围提供了一个边框,并在顶部提供了一个标签。 准备 statcboxsizer 涉及以下步骤

  • 创建一个 wx.StaticBox 对象。
  • 声明一个 wx.StaticBoxSizer 并把上面的静态框作为它的参数。
  • 创建控件并添加 staticbox sizer。
  • 将它设置为框架的sizer。

3.2.2. 实例

import wx
 
class MyWin(wx.Frame):
    def __init__(self, parent, title):
        # super(MyWin, self).__init__(parent, title)
        super().__init__(parent, title = title) 
        self.SetTitle(title=title)
        panel = wx.Panel(self)
        # 主布局
        vbox = wx.BoxSizer(wx.VERTICAL)

        # 第一个静态框大小调整器
        nm = wx.StaticBox(panel, -1, 'Name:') 
        nmSizer = wx.StaticBoxSizer(nm, wx.VERTICAL) 
        
        # 一行四个控件
        nmbox = wx.BoxSizer(wx.HORIZONTAL)
        fn = wx.StaticText(panel, -1, "First Name")
        nm1 = wx.TextCtrl(panel, -1, style = wx.ALIGN_LEFT)
        ln = wx.StaticText(panel, -1, "Last Name")
        nm2 = wx.TextCtrl(panel, -1, style = wx.ALIGN_LEFT)
        nmbox.Add(fn, 0, wx.ALL|wx.CENTER, 5)
        nmbox.Add(nm1, 0, wx.ALL|wx.CENTER, 5)
        nmbox.Add(ln, 0, wx.ALL|wx.CENTER, 5)
        nmbox.Add(nm2, 0, wx.ALL|wx.CENTER, 5)

        nmSizer.Add(nmbox, 0, wx.ALL|wx.CENTER, 10)
        
        # 第二个静态框大小调整器
        sbox = wx.StaticBox(panel, -1, 'buttons:')
        sboxSizer = wx.StaticBoxSizer(sbox, wx.VERTICAL)

        # 一行两个按钮 
        hbox = wx.BoxSizer(wx.HORIZONTAL)
        okButton = wx.Button(panel, -1, 'ok')
        cancelButton = wx.Button(panel, -1, 'cancel')
        hbox.Add(okButton, 0, wx.ALL|wx.LEFT, 10)
        hbox.Add(cancelButton, 0, wx.ALL|wx.LEFT, 10)

        sboxSizer.Add(hbox, 0, wx.ALL|wx.LEFT, 10)

        vbox.Add(nmSizer,0, wx.ALL|wx.CENTER, 5) 
        vbox.Add(sboxSizer,0, wx.ALL|wx.CENTER, 5) 
        panel.SetSizer(vbox) 
        self.Centre() 
            
        # panel.Fit()
        self.Show()
        
if __name__ == '__main__':
    app = wx.App()
    window = MyWin(None, title="StaticBoxSizer")
    window.Show()
    app.MainLoop()

在这里插入图片描述

3.3. 网格布局管理器(wx.GridSizer)

https://www.w3ccoo.com/wxpython/wx_gridsizer.html

3.3.1. 类定义

构造函数:

wx.GridSizer(rows, columns, vgap, hgap):
  • 参数 rows 定义 GridSizer 的行数;
  • 参数 cols 定义 GridSizer 的列数;
  • 参数 vgap 定义垂直方向上行间距;
  • 参数 hgap 定义水平方向上列间距。

常用函数:

  • Add() 在网格中添加一个控件;
  • AddMany() 在网格中添加多个控件;
  • SetRows() 设置Sizer的行数;
  • GetRows() 获得Sizer的行数;
  • SetCols() 设置Sizer的列数;
  • GetCols() 获得Sizer的列数;
  • SetVCap() 设置单元格之间的垂直间隔(像素);
  • GetVCap() 获得单元格自建的垂直间隔;
  • SetHCap() 设置单元格之间的水平间隔(像素);
  • GetHCap() 获得单元格自建的水平间隔。

3.3.2. 实例

网格布局(Grid Layout)将容器划分为网格,控件按照二维数组的方式排列。这种布局方式适合创建复杂的表格状界面,例如电子表格或棋盘游戏界面。

import wx
 
class MyWin(wx.Frame):
    def __init__(self, parent, title):
        # super(MyWin, self).__init__(parent, title)
        super().__init__(parent, title = title) 
        self.SetTitle(title=title)
        panel = wx.Panel(self)            
        gs = wx.GridSizer(4, 4, 5, 5) 
            
        for i in range(1,17): 
            btn = "Btn"+str(i) 
            gs.Add(wx.Button(panel, label=btn), 0, wx.EXPAND) 

            # panel.SetSizer(gs)
        # 面板中添加布局
        panel.SetSizer(gs)
        self.Show()
        
if __name__ == '__main__':
    app = wx.App()
    window = MyWin(None, title="GridSizer")
    window.Show()
    app.MainLoop()

在示例代码中,我们创建了一个有10行5列的网格,随后使用 AutoSizeColumns() 和 AutoSizeRows() 方法自动调整每列每行的大小。
在这里插入图片描述

3.4. 弹性网格布局器(wx.FlexGridSizer)

https://www.w3ccoo.com/wxpython/wx_flexigridsizer.html

3.4.1. 类定义

wx.FlexGridSizer 继承自 wx.GriderSizer,它提供了比 wx.GridSizer 更灵活的网格布局方法,除与 wx.GridSizer 相同功能之外,还增加以下一些功能 :

  • 每行和每列可以有各自的尺寸;
  • 在默认情况下,对尺寸大小进行调节时,会改变行和列的整体尺寸,在 FlexGriderSizer 中,可以指定某行或者某列的尺寸进行调节;
  • 可以在行和列两个方向进行灵活调整,可以为指定个别子元素指定比列量,并且可以指定固定方向上的调整行为。

常用函数:

  • AddGrowableCol(idx, proportion=0) 设定索引为idx的列为可增长列;
  • AddGrowableRow(idx, proportion=0) 设定索引为idx的行为可增长行。
    参数:proportion=0 为默认,表示所有的可增长行或列 按照同比列缩放。如果要指定不一样的缩放比例,那么需要手动设置proportion 值。例如,如 果你有两个尺寸可调整的行,并且它们的 proportion 分别是2和1,那么这第一个行将得到新空间的2/3,第二行将得到 1/3。

3.4.2. 实例

  • 实例一

弹性网格布局器(Flex Grid Sizer)提供了更高级的布局选项,可以动态地根据容器的大小变化调整控件的排列方式。它类似盒式布局,但提供了更多的控制,例如让特定行或列拥有不同的最小尺寸。

import wx
 
class MyWin(wx.Frame):
    def __init__(self, parent, title):
        # super(MyWin, self).__init__(parent, title)
        super().__init__(parent, title = title) 
        self.SetTitle(title=title)
        panel = wx.Panel(self)
 
        # 3行2列的布局,每个控件都有5像素的边距
        flex = wx.FlexGridSizer(3, 2, 5, 5)
        # 添加控件到 flex grid sizer
        flex.Add(wx.StaticText(panel, label="Label 1"), flag=wx.EXPAND|wx.ALL, border=5)
        flex.Add(wx.StaticText(panel, label="Label 2"), flag=wx.EXPAND|wx.ALL, border=5)
        flex.Add(wx.StaticText(panel, label="Label 3"), flag=wx.EXPAND|wx.ALL, border=5)
        flex.Add(wx.StaticText(panel, label="Label 4"), flag=wx.EXPAND|wx.ALL, border=5)
        flex.Add(wx.StaticText(panel, label="Label 5"), flag=wx.EXPAND|wx.ALL, border=5)

        # 面板中添加布局
        panel.SetSizer(flex)
        self.Show()
        
if __name__ == '__main__':
    app = wx.App()
    window = MyWin(None, title="FlexGridSizer")
    window.Show()
    app.MainLoop()

在这里插入图片描述
在该示例中, FlexGridSizer 被用于创建一个3行2列的布局,每个控件都有5像素的边距。通过 flag 参数,可以控制控件填充整个单元格。

  • 实例二
import wx
 
class MyWin(wx.Frame):
    def __init__(self, parent, title):
        # super(MyWin, self).__init__(parent, title)
        super().__init__(parent, title = title) 
        self.SetTitle(title=title)
        panel = wx.Panel(self)
        # 主布局
        hbox = wx.BoxSizer(wx.HORIZONTAL)
            
        fgs = wx.FlexGridSizer(3, 2, 10,10)

        title = wx.StaticText(panel, label = "Title")
        tc1 = wx.TextCtrl(panel)
        author = wx.StaticText(panel, label = "Name of the Author")
        tc2 = wx.TextCtrl(panel)
        review = wx.StaticText(panel, label = "Review")
        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 = 2, flag = wx.ALL|wx.EXPAND, border = 15)

        # 面板中添加布局
        panel.SetSizer(hbox)
        self.Show()
        
if __name__ == '__main__':
    app = wx.App()
    window = MyWin(None, title="FlexGridSizer")
    window.Show()
    app.MainLoop()

在这里插入图片描述
以上设计了一个两列的表单。 第一列包含标签,第二列包含文本框。 第二列设置为可增长。 同样,第三行设置为可增长。 (注意行索引和列索引都是从0开始的)。 AddGrowableCol() 和 AddGrowableRow() 函数中的第二个参数是增长的比例。

3.5. 网格包布局器(wx.GridBagSizer)

在 wxPython 中还提供了一种更灵活的网格布局方式 wx.GridBagSizer, wx.GridBagSizer 显式支持在指定的网格位置添加一个控件,同时也可以指定控件跨越行或者列。因此它可以更灵活地实现更复杂的布局效果。

3.5.1. 类定义

常用方法:

  • Add(): 在网格指定位置处添加一个控件;
  • GetItemPosition(): 返回指定位置的控件项;
  • SetItemPosition(): 在网格指定位置放置一个控件项;
  • GetItemSpan(): 返回一个控件项的行/列跨越数;
  • SetItemSpan(): 设置一个控件项的行/列跨越数。

3.5.2. 实例

import wx
import os
 
class MyWin(wx.Frame):
    def __init__(self, parent, title):
        # super(MyWin, self).__init__(parent, title)
        super().__init__(parent, title = title) 
        self.SetTitle(title=title)
        panel = wx.Panel(self)
        # GridBagSizer 作为 panel 的主布局
        # 5行5列
        sizer = wx.GridBagSizer(5, 5)
 
        # 0行0列
        labelJava = wx.StaticText(panel, label="Java类") # Java class
        sizer.Add(labelJava, 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+"\java_logo.png", wx.BITMAP_TYPE_PNG), size=(100, 100))
        # 0行3列 占1行2列
        sizer.Add(icon, pos=(0, 3), span=(1, 2), flag=wx.TOP|wx.RIGHT|wx.ALIGN_RIGHT, border=5)
 
        # 1行0列 占1行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
        tcName = wx.TextCtrl(panel)
        # 2行0列
        sizer.Add(labelName, pos=(2, 0), flag=wx.LEFT, border=10)
        # 2行1列 占1行3列
        sizer.Add(tcName, pos=(2, 1), span=(1, 3), flag=wx.TOP|wx.EXPAND)
 
        labelPackage = wx.StaticText(panel, label="包")    # Package
        tcPackage = wx.TextCtrl(panel)
        buttonBrowse1 = wx.Button(panel, label="浏览...") # Browse...
        # 3行0列
        sizer.Add(labelPackage, pos=(3, 0), flag=wx.LEFT|wx.TOP, border=10)
        # 3行1列 占1行3列
        sizer.Add(tcPackage, pos=(3, 1), span=(1, 3), flag=wx.TOP|wx.EXPAND, border=5)
        # 3行4列
        sizer.Add(buttonBrowse1, pos=(3, 4), flag=wx.TOP|wx.RIGHT, border=5)
 
        labelExtends = wx.StaticText(panel, label="扩展") # Extends
        comboExtends = wx.ComboBox(panel)
        buttonBrowse2 = wx.Button(panel, label="浏览...") # Browse...
        # 4行0列
        sizer.Add(labelExtends, pos=(4, 0), flag=wx.TOP|wx.LEFT, border=10)
        # 4行1列 占1行3列
        sizer.Add(comboExtends, pos=(4, 1), span=(1, 3), flag=wx.Top|wx.EXPAND, border=5)
        # 4行4列
        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
        chkGeneDefConstructor = wx.CheckBox(panel, label="创建缺省构造函数") # Generate Default Constructor
        chkGeneMainMethod = wx.CheckBox(panel, label="创建Main方法")
        vboxSizer.Add(chkPublic, flag=wx.LEFT|wx.TOP, border=5)
        vboxSizer.Add(chkGeneDefConstructor, flag=wx.LEFT, border=5)       
        vboxSizer.Add(chkGeneMainMethod, flag=wx.LEFT|wx.BOTTOM, border=5)
        # 5行0列 占1行5列
        sizer.Add(vboxSizer, pos=(5, 0), span=(1,5), flag=wx.EXPAND|wx.TOP|wx.LEFT|wx.RIGHT, border=10)

        # 隔1行

        buttonHelp = wx.Button(panel, label="帮助")     # Help
        buttonOK = wx.Button(panel, label="确定")       # OK
        buttonCancel = wx.Button(panel, label="取消")
        # 7行0列
        sizer.Add(buttonHelp, pos=(7, 0), flag=wx.LEFT, border=10)
        # 7行3列
        sizer.Add(buttonOK, pos=(7, 3))
        # 7行4列
        sizer.Add(buttonCancel, pos=(7, 4), span=(1, 1), flag=wx.BOTTOM|wx.RIGHT, border=10)
        
        # 设定索引为idx的列为可增长列
        sizer.AddGrowableCol(2)
 
        panel.SetSizer(sizer)
        sizer.Fit(self)
        
if __name__ == '__main__':
    app = wx.App()
    window = MyWin(None, title="GridBagSizer")
    window.Show()
    app.MainLoop()

在这里插入图片描述

4. 布局管理器的高级用法

4.1. 管理器嵌套与复杂布局

在复杂的应用中,可能会出现很多控件,这时候控件的层次和组合管理就显得尤为重要。层次管理是指合理安排各个控件在布局中的上下文关系,而组合管理指的是将相关的控件组合在一起形成一个逻辑单元。在 wxPython 中,可以使用嵌套的布局管理器来实现复杂的界面布局。

class MyFrame(wx.Frame):
    def __init__(self):
        super(MyFrame, self).__init__(None, title="Complex Layout Demo")
        panel = wx.Panel(self)
        # 初始化布局
        main_sizer = wx.BoxSizer(wx.VERTICAL)
        top_box = wx.BoxSizer(wx.HORIZONTAL)
        left_box = wx.BoxSizer(wx.VERTICAL)
        right_box = wx.BoxSizer(wx.VERTICAL)
        # 左侧布局
        left_box.Add(wx.StaticText(panel, label="Left Box"), flag=wx.EXPAND|wx.ALL, border=5)
        left_box.Add(wx.Button(panel, label="Left Button"), flag=wx.EXPAND|wx.ALL, border=5)
        # 右侧布局
        right_box.Add(wx.StaticText(panel, label="Right Box"), flag=wx.EXPAND|wx.ALL, border=5)
        right_box.Add(wx.Button(panel, label="Right Button"), flag=wx.EXPAND|wx.ALL, border=5)
        # 主布局组合
        top_box.Add(left_box, proportion=1, flag=wx.EXPAND)
        top_box.Add(right_box, proportion=1, flag=wx.EXPAND)
        main_sizer.Add(top_box, proportion=1, flag=wx.EXPAND|wx.ALL, border=5)
        # 面板中添加布局
        panel.SetSizer(main_sizer)

这段代码创建了一个水平的 wx.BoxSizer 作为主要的布局管理器。在其中又嵌套了两个垂直的 wx.BoxSizer ,分别管理左右两侧的控件。通过这种方式,可以将复杂界面的布局分解为更小、更易于管理的部分。
在这里插入图片描述

4.2. 多窗口布局与切换

在更高级的应用中,可能需要使用多个窗口,并在这些窗口之间进行布局切换。wxPython 允许通过多窗口布局来实现复杂的功能。

import wx
 
class ChildWindow(wx.Frame):
    def __init__(self, *args, **kwargs):
        super(ChildWindow, self).__init__(*args, **kwargs)
        panel = wx.Panel(self)
        vbox = wx.BoxSizer(wx.VERTICAL)
        vbox.Add(wx.StaticText(panel, label='Content'), proportion=0, flag=wx.EXPAND|wx.ALL, border=5)
        panel.SetSizer(vbox)
        self.Show()
 
class ParentWindow(wx.Frame):
    def __init__(self, *args, **kwargs):
        super(ParentWindow, self).__init__(*args, **kwargs)
        panel = wx.Panel(self)
        vbox = wx.BoxSizer(wx.VERTICAL)
        # 添加一个按钮用于打开子窗口
        open_child_button = wx.Button(panel, label='Open Child')
        vbox.Add(open_child_button, proportion=0, flag=wx.EXPAND|wx.ALL, border=5)
        # 绑定按钮事件
        self.Bind(wx.EVT_BUTTON, self.OnOpenChild, open_child_button)
        panel.SetSizer(vbox)
        self.Show()
 
    def OnOpenChild(self, event):
        # 打开子窗口
        child = ChildWindow(self)
        child.Show()
 
if __name__ == '__main__':
    app = wx.App(False)
    ParentWindow(None, title='Multiple Windows Layout Example')
    app.MainLoop()

在这里插入图片描述
在上述示例中,我们创建了一个父窗口,并在其中放置了一个按钮。当按钮被点击时,会打开一个新的子窗口,展示额外的内容。
通过这些布局管理器的运用和高级用法的结合,开发者能够构建出既美观又功能强大的桌面应用程序用户界面。

5. 动态布局调整和屏幕适配

随着用户界面设计的发展,开发者面临的一个重要问题是如何在不同分辨率和屏幕尺寸的设备上保持界面的一致性和可用性。

5.1. 设备无关性的界面设计

要创建一个设备无关性的界面设计,可以遵循以下步骤:

  1. 使用布局管理器而非固定位置和大小来安排控件。
  2. 设计响应式布局,自动适应不同的屏幕尺寸。
  3. 使用比例和弹性参数来确保控件在不同屏幕尺寸下都能合理分布。

5.2. 分辨率和屏幕方向适配策略

适配不同分辨率和屏幕方向的策略包括:

  • 为不同屏幕方向(横屏和竖屏)创建多种布局。
  • 监听屏幕尺寸变化事件,并在事件触发时调整布局。
  • 利用布局管理器的动态特性进行必要的布局调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值