qt布局管理

目录

一. 布局管理相关的类

二. 布局可视化设计及其代码原理

1.使用容器组件

2.水平布局

3.网格布局

4.分割条


使用 Qt Designer 可以很方便地进行布 局管理的可视化设计。布局管理也是通过一些类实现的,UI 文件经过 MOC 编译后,可视化设计 的布局管理会被转换为 C++代码。

一. 布局管理相关的类

在 Qt Designer 的组件面板里有用于布局管理的两组组件。在布局管理中还 常用到分割条,分割条对应的类是 QSplitter。布局管理类的继承关系如图所示。

图中 Layouts 分组的 4 个组件对应的布局管理类都继承自 QLayout 类。QLayout 的父类是 QObject 和 QLayoutItem,QLayoutItem 没有父类。因为 QLayout 不是从 QWidget 继承而来的, 所以布局管理类对象并不是窗口上可见的界面组件。

从QLayout继承而来的几个类是常用的布局管理类,有各自的功能特点:

 • QVBoxLayout:垂直布局,使多个组件垂直方向自动布局。

• QHBoxLayout:水平布局,使多个组件水平方向自动布局。

• QGridLayout:网格布局,使多个组件按行和列实现网格状自动布局。

• QFormLayout:表单布局,与 QGridLayout 功能类似,适用于两列组件的布局管理

• QStackedLayout:堆叠布局,这个类对应的组件并没有出现在图中组件面板中。StackedLayout 用于管理多个 QWidget 类对象,也就是多个页面,但 任何时候只有一个页面可见。QStackedLayout 的管理效果与 QStackedWidget 的相似,只是 它没有切换页面的按钮,需要另外编程处理页面切换。

表单布局只适用于两列组件的布局,例如第一列是 QLabel 组件,第二列是 QLineEdit、 QComboBox 等输入组件,构成一种输入表单。表单布局可以看作网格布局的一种简化形式,网格 布局可以管理更复杂的多行多列组件。

即使是同样管理两列组件的布局,表单布局和网格布局也稍微有些差异。表单布局的高度大于最合适的尺寸时,内部的组件的 垂直间距不会再增大,下方多余的空间是空白的。网格布局的高度增大时,内部的组件在垂直方向上是均匀分布的。

QSpacerItem 从 QLayoutItem 继承而来。Horizontal Spacer 和 Vertical Spacer 对应的类均是 QSpacerItem。QSpacerItem 可以用于在布局中占位,或填充剩余空间。

分割条组件类 QSplitter 是从 QWidget 继承而来的,所以它是一个可见的界面组件。分割条一般用于水平或垂直分割来显 两个容器类组件。

二. 布局可视化设计及其代码原理

1.使用容器组件

在可视化设计界面时,最好将一组需要布局管理的组件放置在一个容器组件里,然后对容器 内的组件设置一种布局方式。这样,当容器的大小变化时,容器内组件的大小和位置就能相应自动变化。在设计复杂的界面时,内部有布局的容器组件也可以作为其他容器组件的子组件。

使用布局管理的组件也可以不放在某个容器组件里,而是直接使用布局管理。对于不使用容器组件的布局,其自身就相当于一个容器组件,可以和其他组件再次进行上层布局。

2.水平布局

任何布局类对象在可视化设计时都有 layoutLeftMargin、layoutTopMargin、layoutRightMargin 和 layoutBottomMargin 这 4 个边距属性,这 4 个边距属性用于设置布局组件与父容器的 4 个边距的最小 值,单位是像素。水平布局和垂直布局还有一个属性 layoutSpacing,表示组件的最小间距。

构建项目时,窗口 UI 文件被 MOC 预编译后生成一个头文件,例如 mainwindow.ui 对应的 MOC 预编译结果文件是 ui_mainwindow.h。在 MOC 预编译结果文件的函数 setupUi()中会发现如下的代码,其用于创建图中分组框、3 个按钮和水平布局。为使代码更易懂,我们省略了 每个对象调用 setObjectName()函数设置对象名称的代码。

groupBox = new QGroupBox(MainWindow); //创建 groupBox,将窗口作为父容器
groupBox->setGeometry(QRect(260, 310, 341, 43)); 
horizontalLayout = new QHBoxLayout(groupBox); //在 groupBox 里创建水平布局
horizontalLayout->setSpacing(10); //设置 layoutSpacing 
horizontalLayout->setContentsMargins(5, 5, 5, 5); //设置 4 个边距属性的值
pushButton = new QPushButton(groupBox); 
horizontalLayout->addWidget(pushButton); 
pushButton_2 = new QPushButton(groupBox); 
horizontalLayout->addWidget(pushButton_2); 
pushButton_3 = new QPushButton(groupBox); 
horizontalLayout->addWidget(pushButton_3); 

从上述代码可以看到,创建水平布局对象 horizontalLayout 时,groupBox 是作为其父组件的。 然后 horizontalLayout 运行函数 setSpacing()以设置组件的最小间距,运行函数 setContentsMargins() 设置 4 个边距的值。按钮被创建后,horizontalLayout 运行函数 addWidget()将按钮添加到布局里。

水平布局的 layoutStretch 属性可以灵活控制各组件的宽度占比。图展示了一个分组框中 3 个组件采用水平布局且 layoutStretch 属性值不同时的显示效果。第一个分组框中水平布局的 layoutStretch 属性值为“0,0,0”,表示 3 个组件宽度平均。第二个分组框中水平布局的 layoutStretch 属性值为“0,0,1”,表示两个按钮达到合适宽度后就不再增大,下拉列表框占据右边所有水平空间。 第三个分组框中水平布局的 layoutStretch 属性值为“1,1,2”,这相当于把宽度分为四等份,两个按钮等宽,下拉列表框的宽度是其中一个按钮的 2 倍。

对于水平布局的 layoutStretch 属性实现的效果,还可以通过设置单个组件的 sizePolicy 属性中 的 Horizontal Stretch 来实现。在可视化设计布局时,可以通过配合设置组件的 sizePolicy、 minimumSize、maximumSize 属性,以实现灵活的布局效果。

3.网格布局

可视化设计网格布局时一般是在一个容器组件内先摆放组件,使各组件的位置和大小与期望的效果大致相同,然后点击工具栏上的网格布局按钮进行网格布局。

网格布局的属性设置及效果如图所示:

网格布局是划分为行和列的,除了4个边距属性,网格布局还有几个特有的属性。

• layoutHorizontalSpacing:水平方向上组件的最小间距。

• layoutVerticalSpacing:垂直方向上组件的最小间距。

• layoutRowStretch:各行的延展因子,与垂直布局的 layoutStretch 属性功能相同。

• layoutColumnStretch:各列的延展因子,与水平布局的 layoutStretch 属性功能相同。

• layoutRowMinimumHeight:各行的最小高度,单位是像素,若值是 0 则表示自动设置。

• layoutColumnMinimumWidth:各列的最小宽度,单位是像素,若值是 0 则表示自动设置。

• layoutSizeConstraint:布局的尺寸限制方式,其值是枚举类型 QLayout::SizeConstraint,默认设置为 QLayout::SetDefaultConstraint,也就是将父组件的最小尺寸作为网格布局的最小尺寸。

UI 文件经过 MOC 预编译后,可以在生成的头文件里找到实现网格布局的代码。例如,对于上图所示的分组框的网格布局,函数 setupUi()中的实现代码如下。为使代码更易懂,省略每个对象调用 setObjectName()函数设置对象名称的代码。

groupBox = new QGroupBox(MainWindow); //创建 groupBox,将窗口作为父容器
groupBox->setGeometry(QRect(290, 160, 200, 230)); 
gridLayout = new QGridLayout(groupBox); //创建网格布局,将 groupBox 作为父容器
gridLayout->setHorizontalSpacing(7); 
gridLayout->setVerticalSpacing(12); 
gridLayout->setContentsMargins(10, 10, -1, -1); 
pushButton = new QPushButton(groupBox); 
gridLayout->addWidget(pushButton, 0, 0, 1, 1); //添加左上角的按钮
pushButton_2 = new QPushButton(groupBox); 
gridLayout->addWidget(pushButton_2, 0, 1, 1, 1); 
comboBox = new QComboBox(groupBox); 
comboBox->addItem(QString()); 
gridLayout->addWidget(comboBox, 1, 0, 1, 2); //添加下拉列表框
plainTextEdit = new QPlainTextEdit(groupBox); 
gridLayout->addWidget(plainTextEdit, 2, 0, 1, 2); 

QGridLayout 类添加组件的函数是 addWidget(),其函数原型定义如下:

void QGridLayout::addWidget(QWidget *widget, int fromRow, int fromColumn, int rowSpan, 
 int columnSpan, Qt::Alignment alignment = Qt::Alignment()) 

其中,widget 是需要添加到布局中的组件,fromRow 和 fromColumn 表示组件所在的行号和列号, rowSpan 和 columnSpan 表示组件占用的行数和列数,alignment 表示默认的对齐方式。

上图所示的网格布局有 3 行 2 列,添加左上角按钮 pushButton 的语句是:

gridLayout->addWidget(pushButton, 0, 0, 1, 1); 

这表示将 pushButton 添加到网格布局的 0 行 0 列的位置,pushButton 占用 1 行 1 列。

添加下拉列表框组件 comboBox 的语句是:

gridLayout->addWidget(comboBox, 1, 0, 1, 2);

这表示将 comboBox 添加到网格布局的 1 行 0 列的位置,comboBox 占用 1 行 2 列。

在设计网格布局的时候,并不意味着每个网格里都必须有组件,网格可以空着,也可以使用 水平或垂直间隔组件占位。

4.分割条

实现分割条功能的类是 QSplitter,分割条可以实现 水平分割或垂直分割,一般是在两个可以自由改变大小 的组件之间进行分割。图中所示为在一个窗体上对两 个组件采用水平分割布局的效果,一个分组框和一个 QPlainTextEdit 组件水平分割布局。可视化设计时同时选 中这两个组件,再点击工具栏上的 Lay Out Horizontally in Splitter 按钮即可。

QSplitter 是界面组件,所以可以使用 QMainWindow::setCentralWidget()函数将其设置为主窗口 的中心组件,也就是填充满主窗口的工作区。QSplitter 布局组件有以下几个属性。

• orientation:方向,即水平分割或垂直分割。

• opaqueResize:如果值是 true,表示拖动分割条时,组件是动态改变大小的。

• handleWidth:进行分割操作的拖动条的宽度,单位是像素。

• childrenCollapsible:表示进行分割操作时,子组件的大小是否可以变为 0。

图 中的 UI 文件被 MOC 预编译后生成 C++头文件,其中的函数 setupUi()中有如下的代 码,它创建了图中的分割条和两个子组件。

splitter = new QSplitter(Form); //创建 splitter,窗口对象是 Form 
splitter->setOrientation(Qt::Horizontal); 
splitter->setOpaqueResize(true); 
splitter->setHandleWidth(8); 
splitter->setChildrenCollapsible(true); 
groupBox = new QGroupBox(splitter); 
groupBox->setMinimumSize(QSize(150, 0)); //设置最小宽度
splitter->addWidget(groupBox); //添加到分割布局中
plainTextEdit = new QPlainTextEdit(splitter); 
splitter->addWidget(plainTextEdit); //添加到分割布局中

由代码可见,创建分割布局就是将分割条对象 splitter 作为两个组件 groupBox 和 plainTextEdit 的父容器组件。我们在可视化设计 UI 时还为 groupBox 设置 minimumSize.Width 属性值为 150,这 样在分割操作时,groupBox 达到最小宽度后就不能再缩小。

可视化设计的窗口 UI 文件最后是经过 MOC 预编译成 C++程序的,所以可视化设计的布局都有对应的代码,理论上可以采用纯代码方式创建界面,但是纯代码方式相对于可视化设计方式效率太低,且界面复杂时编码难度大。所以,应尽量使用 Qt Designer 可视化设计窗口界面,当某些界面效果不能通过可视化设计实现时,可以通过添加代码来补充创建界面。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值