news 2026/1/22 7:34:12

【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/1/21 4:39:45

29、系统性能问题排查指南

系统性能问题排查指南 在 IT 运维工作中,我们常常会遇到各种系统性能问题,比如服务器变慢、应用程序响应不佳等。这些问题不仅影响用户体验,还可能对业务造成损失。本文将围绕系统的四个核心元素:CPU、内存、存储设备和网络负载管理,详细介绍如何排查和解决系统性能问题。…

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

32、网络与外设故障排查全攻略

网络与外设故障排查全攻略 网络故障排查 在处理网络问题时,了解 NetworkManager 隐藏工作文件的位置很有必要。系统中有几个关键的目录和文件存储着网络配置信息: - /etc/NetworkManager/ 目录下有一个名为 NetworkManager.conf 的配置文件。 - /etc/NetworkManager/…

作者头像 李华
网站建设 2026/1/14 2:34:52

ubuntu配置Cuda

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 看显卡类型 //////////…

作者头像 李华
网站建设 2026/1/16 5:09:10

25、使用 SpamAssassin 对抗垃圾邮件(上)

使用 SpamAssassin 对抗垃圾邮件(上) 在当今数字化时代,垃圾邮件泛滥成灾,严重影响了我们的工作和生活。SpamAssassin 作为一款强大的开源垃圾邮件过滤工具,为我们提供了有效的解决方案。本文将详细介绍 SpamAssassin 的使用方法和配置技巧,帮助你更好地应对垃圾邮件的挑…

作者头像 李华