news 2026/9/3 0:04:11

【wxWidgets教程】界面布局:wxSizer调整器使用详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【wxWidgets教程】界面布局:wxSizer调整器使用详解

继上一篇【wxWidgest教程】界面布局:自动布局之后,本篇将进入介绍界面布局器wxSizer的使用方法。wxWidgets教程完整目录

调整器使用的布局算法与其他GUI工具包(如Java的AWT、GTK工具包或Qt工具包)中的布局系统几乎相同。它基于单个子窗口报告其最小所需大小以及在父窗口大小发生更改时拉伸。这通常意味着您不设置对话框的启动大小,而是为对话框分配一个调整器,并询问这个调整器的建议大小,调整器将依次查询其子级(可以是普通窗体、空白区域或其他调整器),以便可以构造调整器的层次结构。

使调整器非常适合在wxWidgets中使用的原因是,每个控件都报告自己的最小大小,并且算法可以处理不同平台上字体大小或不同窗口(对话框项)大小的差异,而不会出现问题。例如,如果标准字体以及Linux/GTK小部件的总体设计需要比Windows上更多的空间,那么Linux/GTK上的初始对话框大小将自动比Windows上的大。

调整器同时也是一类容器,用于布局并包含子控件。使用wxWindow::Show()方法,可以像隐藏任何控件一样隐藏大小调整器中包含的控件。不过,wxSizer还提供了一个单独的方法,可以告诉调整器在其大小计算中不要考虑该控件。调用boolShow(wxWindow*window,boolshow=true,boolrecursive=false ),然后必须调用调整器上的void wxSizer::Layout()来强制更新。这在隐藏部分窗口时很有用,因为您可以避免从调整器中删除控件,以后再添加它们,仅wxBoxSizerwxFlexGridSizer支持该功能。

一、一维布局

(一)wxBoxSizer

wxBoxSizer基于这样一个认识,即窗口通常以非常简单的基本几何形式布局,通常是一行或一列。

wxBoxSizer可以垂直或水平布局其子项,具体取决于其构造函数wxBoxSizer(intorient)中使用的标志是。orient为wxVERTICAL,使用垂直方向排列,每个子项都可以居中、右对齐或左对齐。相应地,orient为wxHORIZONTAL,水平方向排列,每个子项都可以居中、在底部对齐或在顶部对齐。拉伸因子用于主方向,确定子项水平或垂拉伸的程度。

下面的示例演示wxBoxSizer的使用,例子同时使用了两种标志设置方式。

MyFrame::MyFrame(wxWindowID id,const wxString& title,const wxPoint& pos, const wxSize& size ,long style , const wxString& name):wxFrame(NULL,id,title,pos,size,style,name){ //ctor wxSizerFlags sizerFlag; sizerFlag.Border(wxALL,1).Proportion(1).Expand(); wxBoxSizer* outBox=new wxBoxSizer(wxVERTICAL); wxBoxSizer* hBox1=new wxBoxSizer(wxHORIZONTAL); hBox1->Add(new wxButton(this,wxID_ANY,"Test Button 1"),sizerFlag); hBox1->Add(new wxButton(this,wxID_ANY,"Test Button 2"),1,wxEXPAND|wxALL); wxBoxSizer* hBox2=new wxBoxSizer(wxHORIZONTAL); hBox2->Add(new wxTextCtrl(this,wxID_ANY,"hbox2 text box1", wxDefaultPosition,wxDefaultSize, wxTE_MULTILINE),sizerFlag); hBox2->Add(new wxTextCtrl(this,wxID_ANY,"hbox2 text box2", wxDefaultPosition,wxDefaultSize, wxTE_MULTILINE),2,wxEXPAND|wxALL); hBox2->Add(new wxTextCtrl(this,wxID_ANY,"hbox2 text box3", wxDefaultPosition,wxDefaultSize, wxTE_MULTILINE),1,wxEXPAND|wxALL); outBox->Add(hBox1,sizerFlag); outBox->Add(hBox2,wxSizerFlags(1).Expand().Border(wxALL)); SetSizerAndFit(outBox); }

(二)wxStaticBoxSizer

wxStaticBoxSizer与wxBoxSizer相同,但由一个静态框包围。下面是一个示例:

MyFrame::MyFrame(wxWindowID id,const wxString& title):wxFrame(NULL,id,title){ //ctor wxBoxSizer *topSizer=new wxBoxSizer(wxVERTICAL); wxStaticBoxSizer* sizer1=new wxStaticBoxSizer(wxHORIZONTAL,this,"wxStaticBoxSizer"); sizer1->Add(new wxCheckBox(this,wxID_ANY,"option 1"),wxALL|wxEXPAND); sizer1->Add(new wxCheckBox(this,wxID_ANY,"option 2"),wxALL|wxEXPAND); sizer1->Add(new wxCheckBox(this,wxID_ANY,"option 3"),wxALL|wxEXPAND); sizer1->Add(new wxCheckBox(this,wxID_ANY,"option 4"),wxALL|wxEXPAND); wxStaticBoxSizer* sizer2=new wxStaticBoxSizer(wxHORIZONTAL,this,"wxStaticBoxSizer"); sizer2->Add(new wxCheckBox(this,wxID_ANY,"option 1"),wxALL|wxEXPAND); sizer2->Add(new wxCheckBox(this,wxID_ANY,"option 2"),wxALL|wxEXPAND); sizer2->Add(new wxCheckBox(this,wxID_ANY,"option 3"),wxALL|wxEXPAND); sizer2->Add(new wxCheckBox(this,wxID_ANY,"option 4"),wxALL|wxEXPAND); topSizer->Add(sizer1,wxSizerFlags(1).Expand().Border(wxALL)); topSizer->Add(sizer2,wxSizerFlags(1).Expand().Border(wxALL)); SetSizerAndFit(topSizer); }

(三)wxWrapSizer

一个wxWrapSizer将它的子项排成一行,就像wxBoxSizer一样,只要在主方向有可用的空间,不同的是,当空间占满后,wxWrapSizer将在次方向上添加新行或列。

二、二维布局

(一)wxGridSizer

wxGridSizer是一个二维的调整器。所有子项都被赋予相同的大小,其大小与最大子项所需的最小大小相同。在本例中是左下边框中的文本控件。列数或行数都是固定的,如果添加了新的子项,则网格大小调整器将按各自的其他方向增长:

MyFrame::MyFrame(wxWindowID id , const wxString& title) : wxFrame( nullptr, id, title){ //ctor wxGridSizer *sizer=new wxGridSizer(4,3,wxSize(1,1)); wxString btnNames[]={"0","1","2","3","4","5","6","7","8","9","+","-"}; for(wxString bn:btnNames){ sizer->Add(new wxButton(this,wxWindow::NewControlId(),bn), wxSizerFlags(1).Expand().Border(wxALL,1)); } SetSizerAndFit(sizer); }

在wxSizer的基础上,wxGridSizer增加了如下函数,用于设置网络的行列数及行列之间的间隔:voidSetRows(introws);voidSetCols(introws);voidSetVGap(intgap);voidSetHGap(intgap);

(二)wxFlexGridSizer

从wxGridSizer派生的另一个二维调整器。每一列的宽度和每一行的高度是根据各自最大的子级的最小要求分别计算的。此外,如果为调整器分配的大小不同于它所请求的大小,则可以将列和行声明为可扩展的。下面的示例显示的对话框与上面的示例相同,但使用的是wxFlexGridSizer:

MyFrame::MyFrame(wxWindowID id ,const wxString& title) : wxFrame( nullptr, id, title) { //ctor wxFlexGridSizer *sizer=new wxFlexGridSizer(4,3,wxSize(1,1)); wxString btnNames[]={"0","1","2","3","4"," 5+3=5; 2*222=444 \r\nf(n)=100*n", "6","7","8","9","+","-"}; for(wxString bn:btnNames){ sizer->Add(new wxButton(this,wxWindow::NewControlId(),bn),wxSizerFlags(1).Expand().Border(wxALL,1)); } SetSizerAndFit(sizer); }

在wxGridSizer的基础上,wxFlexGridSizer增加了以下操作:

设置行列拉伸因子

如同一维布局中子控件的proportion参数一样,在二维弹性布局中,行和列也具有拉伸因子,当调整器中有额外的空间时,该拉伸因子决定了行或列如何扩展以填充剩余空间。通过voidAddGrowableCol(size_tidx,intproportion=0)voidAddGrowableRow(size_tidx,intproportion=0)函数可以设置行或列的拉伸因子。idx:从0开始计数,标识行号或列号;proportion:行或列的空间占比大小。

如果取消空间占比,则可调用voidRemoveGrowableCol(size_tidx)voidRemoveGrowableRow(size_tidx)函数。boolIsRowGrowable(size_tidx)boolIsColGrowable(size_tidx)可判断特定行列是否可拉伸。

设置拉伸方向

从wxWidgets 2.5.0开始,wxFlexGridSizer还可以在一个方向上等长调整控件大小,而在另一个方向则相对灵活,不要求长度相等。可以调用voidSetFlexibleDirection(intdirection)设置这个相对灵活的方向,参数direction可以是wxVERTICAL、wxHORIZONTAL或wxBOTH。而在另一个方向则需要调用voidSetNonFlexibleGrowMode(wxFlexSizerGrowModemode)设置子控件填充剩余空间的方式。mode可以设置为下面的值:

表 11wxFlexSizerGrowMode定义

wxFLEX_GROWMODE_NONE

Sizer不会在非弹性方向上拉伸其子控件

wxFLEX_GROWMODE_SPECIFIED

Sizer使用AddGrowtableCol()和AddGrowtableRow()设置的proportion来决定列或行的最小大小(这是默认值)

wxFLEX_GROWMODE_ALL

Sizer平等地拉伸所有列或行,与proportion参数无关

(三)wxGridBagSizer

wxGridBagSizer可以像wxFlexGridSizer一样在虚拟网格中布局控件。与之不同的是,该调整器还能够使用wxGBPosition显式地指定以(col、row)为坐标指定的网格位置,以及使用wxGBSpan指定子控件占用的行数、列数,类似于HTML<table>中的colspan和rowspan属性。该调整器的子项添加操作与其父类不同:

wxSizerItem*Add(wxWindow*window,const wxGBPosition&pos,
const wxGBSpan&span=wxDefaultSpan,
intflag=0,intborder=0,
wxObject*userData=NULL);

三、总结

本文介绍了wxWidgets中wxSizer布局器的使用方法。wxSizer采用基于控件最小大小和拉伸因子的布局算法,支持跨平台自适应。文章详细讲解了一维布局器(wxBoxSizer、wxStaticBoxSizer、wxWrapSizer)和二维布局器(wxGridSizer、wxFlexGridSizer、wxGridBagSizer)的特点及使用场景。重点说明了弹性布局中的行列拉伸因子设置、控件隐藏方法等实用功能,并通过代码示例展示了各类布局器的实际应用。

还有一些界面布局的高级用法,如标准布局、弹簧等,后续将进一步讨论。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/2 21:25:24

革命性EPUB阅读解决方案:Awaken智能同步系统

革命性EPUB阅读解决方案&#xff1a;Awaken智能同步系统 【免费下载链接】Awaken 一个基于WebDAV的全平台EPUB阅读器&#xff0c;支持笔记、进度、书签同步&#xff0c;支持Kindle笔记导入。 项目地址: https://gitcode.com/gh_mirrors/aw/Awaken 在数字阅读时代&#x…

作者头像 李华
网站建设 2026/9/1 22:15:21

23、保障网络连接安全:创建VPN或DMZ

保障网络连接安全:创建VPN或DMZ 在当今数字化时代,网络安全至关重要。VPN(虚拟专用网络)和DMZ(非军事区)是两种常用的网络安全技术,它们可以帮助我们保护网络连接的安全。本文将详细介绍如何创建VPN和DMZ,并提供相应的操作步骤和测试方法。 1. 创建OpenVPN隧道 启动…

作者头像 李华
网站建设 2026/9/2 21:52:03

腾讯SRPO:10分钟训练让AI生图真实感提升3倍,告别“塑料质感“

腾讯SRPO&#xff1a;10分钟训练让AI生图真实感提升3倍&#xff0c;告别"塑料质感" 【免费下载链接】SRPO 腾讯SRPO是基于FLUX.1.dev优化的文本生成图像模型&#xff0c;采用Direct-Align技术提升降噪效率&#xff0c;通过语义相对偏好优化实现奖励在线调整。无需依赖…

作者头像 李华
网站建设 2026/9/2 10:24:59

springboot基于vue的电子小说书城系统_9wv9nd88

目录已开发项目效果实现截图开发技术系统开发工具&#xff1a;核心代码参考示例1.建立用户稀疏矩阵&#xff0c;用于用户相似度计算【相似度矩阵】2.计算目标用户与其他用户的相似度系统测试总结源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&…

作者头像 李华
网站建设 2026/9/2 21:50:07

实时云渲染的技术原理是什么?哪个实时云渲染系统更好?

在数字化时代&#xff0c;实时云渲染技术正逐渐改变图形处理和内容交互的方式。无论是游戏、虚拟现实、工业设计还是在线教育&#xff0c;实时云渲染都能通过云端强大的计算能力&#xff0c;将高质量的图形内容实时传输到终端设备&#xff0c;降低对本地硬件的要求。那么&#…

作者头像 李华
网站建设 2026/9/2 22:35:11

springboot基于vue的电竞赛事报名裁判管理系统_24a4vc46

目录 已开发项目效果实现截图开发技术系统开发工具&#xff1a; 核心代码参考示例1.建立用户稀疏矩阵&#xff0c;用于用户相似度计算【相似度矩阵】2.计算目标用户与其他用户的相似度系统测试总结源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&am…

作者头像 李华