Qt C++ :QLayout 布局管理

文章目录


布局管理相关的类

因为QLayout不是从QWidget继承而来的,所以布局管理类对象并不是窗口上可见的界面组件。


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

  • QVBoxLayout:垂直布局,使多个组件垂直方向自动布局。
  • QHBoxLayout:水平布局,使多个组件水平方向自动布局。
  • QGridLayout:网格布局,使多个组件按行和列实现网格状自动布局。
  • QFormLayout:表单布局,与QGridLayout功能类似,适用于两列组件的布局管理。
  • QStackedLayout:堆叠布局。QStackedLayout用于管理多个QWidget类对象,也就是多个页面,但
    任何时候只有一个页面可见。QStackedLayout的管理效果与QStackedWidget的相似,只是它没有切换页面的按钮,需要另外编程处理页面切换。

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

即使是同样管理两列组件的布局,表单布局和网格布局也稍微有些差异。

表单布局GroupBox1的高度大于最合适的尺寸时,内部的组件的垂直间距不会再增大,下方多余的空间是空白的。

网格布局GroupBox2的高度增大时,内部的组件在垂直方向上是均匀分布的。

QSpacerItemQLayoutItem继承而来,Horizontal SpacerVertical Spacer 对应的类均是QSpacerItemQSpacerItem可以用于在布局中占位或填充剩余空间。

分割条组件类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() 方法,可通过以下方式清空:

    clike 复制代码
    QLayout* layout = widget->layout();
    QLayoutItem* item;
    while ((item = layout->takeAt(0))) {
        if (item->widget()) item->widget()->deleteLater();
        if (item->layout()) delete item->layout();
        delete item;
    }
  • 调试布局

    可临时设置背景色帮助调试:

    clike 复制代码
    widget->setStyleSheet("background: yellow;");

分割条QSplitter

实现分割条功能的类是QSplitter,分割条可以实现水平分割或垂直分割,一般是在两个可以自由改变大小的组件之间进行分割。可视化设计时同时选中这两个组件,再点击工具栏上的LayOut Horizontally in Splitter按钮(使用分裂器在水平方向布局)即可。

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

  • orientation:方向,即水平分割或垂直分割。
  • opaqueResize:如果值是true,表示拖动分割条时,组件是动态改变大小的。
  • handleWidth:进行分割操作的拖动条的宽度,单位是像素。
  • childrenCollapsible:分割操作时,子组件的大小是否可以变为0。
相关推荐
Univin4 小时前
C++(10.4)
开发语言·数据结构·c++
KyollBM4 小时前
每日羊题 (质数筛 + 数学 | 构造 + 位运算)
开发语言·c++·算法
Univin6 小时前
C++(10.5)
开发语言·c++·算法
AA陈超6 小时前
虚幻引擎UE5专用服务器游戏开发-33 在上半身播放组合蒙太奇
c++·游戏·ue5·游戏引擎·虚幻
qq_428639616 小时前
虚幻基础:组件间的联动方式
c++·算法·虚幻
怎么没有名字注册了啊7 小时前
C++后台进程
java·c++·算法
slim~8 小时前
CLion实现ini 解析器设计与实现
c++·后端·clion
AA陈超9 小时前
虚幻引擎5 GAS开发俯视角RPG游戏 P05-05 游戏效果委托
c++·游戏·ue5·游戏引擎·虚幻
杨小码不BUG9 小时前
Davor的北极探险资金筹集:数学建模与算法优化(洛谷P4956)
c++·算法·数学建模·信奥赛·csp-j/s