文章目录
- 布局管理相关的类
- 布局可视化设计
- 核心属性与设置接口
-
- 边距(Margins)
- 控件间距(Spacing)
- 对齐方式(Alignment)
- [尺寸策略(Size Policy)](#尺寸策略(Size Policy))
- [伸缩因子(Stretch Factor)](#伸缩因子(Stretch Factor))
- [嵌套布局(Nested Layouts)](#嵌套布局(Nested Layouts))
- [QGridLayout 网格布局](#QGridLayout 网格布局)
- [QFormLayout 表单布局](#QFormLayout 表单布局)
- 注意事项
- 分割条QSplitter
布局管理相关的类
因为QLayout不是从QWidget继承而来的,所以布局管理类对象并不是窗口上可见的界面组件。
从QLayout继承而来的几个类是常用的布局管理类,有各自的功能特点。
QVBoxLayout
:垂直布局,使多个组件垂直方向自动布局。QHBoxLayout
:水平布局,使多个组件水平方向自动布局。QGridLayout
:网格布局,使多个组件按行和列实现网格状自动布局。QFormLayout
:表单布局,与QGridLayout功能类似,适用于两列组件的布局管理。QStackedLayout
:堆叠布局。QStackedLayout用于管理多个QWidget类对象,也就是多个页面,但
任何时候只有一个页面可见。QStackedLayout的管理效果与QStackedWidget的相似,只是它没有切换页面的按钮,需要另外编程处理页面切换。
表单布局只适用于两列组件的布局,例如第一列是QLabel组件,第二列是QLineEdit、QComboBox等输入组件,构成一种输入表单。表单布局可以看作网格布局的一种简化形式,网格布局可以管理更复杂的多行多列组件。
即使是同样管理两列组件的布局,表单布局和网格布局也稍微有些差异。
表单布局GroupBox1的高度大于最合适的尺寸时,内部的组件的垂直间距不会再增大,下方多余的空间是空白的。
网格布局GroupBox2的高度增大时,内部的组件在垂直方向上是均匀分布的。
QSpacerItem
从QLayoutItem
继承而来,Horizontal Spacer
和Vertical Spacer
对应的类均是QSpacerItem
。QSpacerItem
可以用于在布局中占位或填充剩余空间。
分割条组件类QSplitter
是从QWidget
继承而来的,所以它是一个可见的界面组件。分割条一般用于水平或垂直分割来显示两个容器类组件。
布局可视化设计
使用容器组件
在可视化设计界面时,最好将一组需要布局管理的组件放置在一个容器组件里,然后对容器内的组件设置一种布局方式。这样,当容器的大小变化时,容器内组件的大小和位置就能相应自动变化。在设计复杂的界面时,内部有布局的容器组件也可以作为其他容器组件的子组件。
使用布局管理的组件也可以不放在某个容器组件里,而是直接使用布局管理。对于不使用容器组件的布局,其自身就相当于一个容器组件,可以和其他组件再次进行上层布局。
核心属性与设置接口
以下是 QLayout
及其子类中常用的属性及其对应的设置方法。
边距(Margins)
控制布局与父控件边缘之间的距离。
属性:contentsMargins
接口:
clike
void setContentsMargins(int left, int top, int right, int bottom);
void setContentsMargins(const QMargins &margins);
QMargins contentsMargins() const;
示例:
clike
layout->setContentsMargins(10, 10, 10, 10); // 四周边距10px
提示:setMargin(int)(已弃用),推荐使用 setContentsMargins()。
控件间距(Spacing)
控制布局内部控件之间的间距。
属性:spacing
接口:
clike
void setSpacing(int spacing);
int spacing() const;
示例:
clike
layout->setSpacing(5); // 控件间间隔5px
注意:某些布局(如 QFormLayout)可能有自己的 horizontalSpacing 和 verticalSpacing。
对齐方式(Alignment)
控制控件在布局中的对齐方式。
接口:
clike
void setAlignment(QWidget *widget, Qt::Alignment alignment);
void setAlignment(QLayout *layout, Qt::Alignment alignment); // 嵌套布局对齐
常用对齐常量:
Qt::AlignLeft
, Qt::AlignRight
Qt::AlignTop
, Qt::AlignBottom
Qt::AlignCenter
, Qt::AlignHCenter
, Qt::AlignVCenter
示例:
clike
QHBoxLayout *hLayout = new QHBoxLayout;
QLabel *label = new QLabel("Hello");
hLayout->addWidget(label);
hLayout->setAlignment(label, Qt::AlignRight); // 右对齐
尺寸策略(Size Policy)
虽然 QLayout 不直接管理尺寸策略,但控件的 QSizePolicy 会影响布局行为。
设置接口(在控件上):
clike
void setSizePolicy(QSizePolicy::Policy horizontal, QSizePolicy::Policy vertical);
常用策略:
Fixed
:固定大小Minimum
:最小尺寸,可拉伸Expanding
:优先扩展Preferred
:理想大小
示例:
clike
button->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
伸缩因子(Stretch Factor)
控制布局中控件或子布局的拉伸比例。
接口:
clike
void addStretch(int stretch = 1); // 添加弹性空白
void addSpacerItem(QSpacerItem *spacer); // 添加自定义间隔
void setRowStretch(int row, int stretch); // QGridLayout 行伸缩
void setColumnStretch(int column, int stretch); // 列伸缩
示例:
clike
QVBoxLayout *vLayout = new QVBoxLayout;
vLayout->addWidget(new QPushButton("Top"));
vLayout->addStretch(1); // 中间空白区域拉伸
vLayout->addWidget(new QPushButton("Bottom"));
嵌套布局(Nested Layouts)
布局可以嵌套使用,实现复杂界面。
接口:
clike
void addLayout(QLayout *layout);
示例:
clike
QHBoxLayout *hLayout = new QHBoxLayout;
QVBoxLayout *vLayout = new QVBoxLayout;
vLayout->addWidget(new QLabel("Name:"));
vLayout->addWidget(new QLineEdit());
hLayout->addLayout(vLayout);
hLayout->addWidget(new QPushButton("OK"));
QGridLayout 网格布局
添加控件到指定位置:
clike
void addWidget(QWidget *widget, int row, int column, Qt::Alignment alignment = {});
void addWidget(QWidget *widget, int fromRow, int fromColumn, int rowSpan, int columnSpan);
设置行列伸缩:
clike
setRowStretch(int row, int stretch);
setColumnStretch(int column, int stretch);
设置行列间距:
clike
setHorizontalSpacing(int);
setVerticalSpacing(int);
使用 QSpacerItem 手动插入空白项
当你需要在特定位置插入空白(比如底部留空、右侧留空),可以使用 QSpacerItem。
clike
// 水平 + 垂直可拉伸的空白
QSpacerItem* verticalSpacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
// 插入到第3行,第0列,跨越2行
gridLayout->addItem(verticalSpacer, 3, 0, 2, 1);
常见 QSpacerItem 类型
类型 | 代码 |
---|---|
垂直空白(可拉伸) | new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding) |
水平空白(可拉伸) | new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum) |
固定大小空白 | new QSpacerItem(50, 30, QSizePolicy::Fixed, QSizePolicy::Fixed) |
✅ 优点:精确控制位置和尺寸
✅ 适用:在特定行/列插入空白,如底部留空、右侧填充
使用 addRow() 后添加 addStretch() 控制拉伸
虽然 QGridLayout 没有直接的 addStretch()
,但可以通过 设置行或列的伸缩因子 来实现类似效果。
clike
gridLayout->addWidget(new QLabel("用户名:"), 0, 0);
gridLayout->addWidget(new QLineEdit(), 0, 1);
gridLayout->addWidget(new QLabel("密码:"), 1, 0);
gridLayout->addWidget(new QLineEdit(), 1, 1);
// 让第2行(按钮下方)可拉伸,从而将内容"顶"到上方
QPushButton* btn = new QPushButton("登录");
gridLayout->addWidget(btn, 2, 0, 1, 2);
// 设置第3行可拉伸(最后一行)
gridLayout->setRowStretch(3, 1);
✅ 优点:实现"内容靠上,底部留白"的经典布局
💡 类似 QVBoxLayout
中的 addStretch()
QFormLayout 表单布局
添加表单项:
clike
void addRow(const QString &labelText, QWidget *field);
void addRow(QWidget *label, QWidget *field);
设置标签对齐:
clike
void setLabelAlignment(Qt::Alignment alignment);
设置表单项间距:
clike
setHorizontalSpacing(10);
setVerticalSpacing(5);
注意事项
-
避免手动设置控件位置
一旦使用布局,就不要调用
move()
或setGeometry()
,否则布局会被破坏。 -
及时设置父对象或布局
控件添加到布局后,会自动被设置为布局所在
widget
的子对象,无需手动setParent()
。 -
合理使用 stretch 和 spacer
使用
addStretch()
或QSpacerItem
控制空白区域,避免硬编码大小。 -
布局清空与重置
Qt 没有直接的
clear()
方法,可通过以下方式清空:clikeQLayout* layout = widget->layout(); QLayoutItem* item; while ((item = layout->takeAt(0))) { if (item->widget()) item->widget()->deleteLater(); if (item->layout()) delete item->layout(); delete item; }
-
调试布局
可临时设置背景色帮助调试:
clikewidget->setStyleSheet("background: yellow;");
分割条QSplitter
实现分割条功能的类是QSplitter,分割条可以实现水平分割或垂直分割,一般是在两个可以自由改变大小的组件之间进行分割。可视化设计时同时选中这两个组件,再点击工具栏上的LayOut Horizontally in Splitter
按钮(使用分裂器在水平方向布局)即可。
QSplitter
是界面组件,所以可以使用QMainWindow:setCentralWidget()
函数将其设置为主窗口的中心组件,也就是填充满主窗口的工作区。QSplitter
布局组件有以下几个属性。
orientation
:方向,即水平分割或垂直分割。opaqueResize
:如果值是true,表示拖动分割条时,组件是动态改变大小的。handleWidth
:进行分割操作的拖动条的宽度,单位是像素。childrenCollapsible
:分割操作时,子组件的大小是否可以变为0。