跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++

Qt 布局管理器详解:QVBoxLayout、QHBoxLayout、QGridLayout、QFormLayout

Qt 布局管理器用于界面控件的自动排列与窗口自适应。主要包含垂直布局 QVBoxLayout、水平布局 QHBoxLayout、网格布局 QGridLayout 和表单布局 QFormLayout。通过 setLayout 设置布局,支持嵌套。QGridLayout 支持行列定位及拉伸系数设置,需注意 QSizePolicy 策略。Spacer 可用于添加空白间距。掌握这些工具可简化界面设计流程,提高布局灵活性和可维护性。

RefactorPro发布于 2026/3/22更新于 2026/10/2497 浏览
Qt 布局管理器详解:QVBoxLayout、QHBoxLayout、QGridLayout、QFormLayout

Qt 布局管理器详解

在 Qt 开发中,界面布局的合理设计是提升用户体验的关键。早期开发者常采用绝对定位的方式摆放控件,即通过计算坐标并使用 setGeometry 或 move 方法逐一定位。然而,这种方法不仅复杂且不精确,难以适应窗口大小的变化,尤其在界面内容繁杂时,计算难度显著增加。

为解决这一问题,Qt 引入了布局管理器机制,通过 QVBoxLayout(垂直布局)、QHBoxLayout(水平布局)、QGridLayout(网格布局)和 QFormLayout(表单布局)等工具,实现了控件的自动排列与窗口大小的自适应调整。布局管理器不仅简化了界面设计流程,还提高了布局的灵活性和可维护性,成为 Qt 开发中不可或缺的一部分。

布局管理器概述

之前使用 Qt 在界面上创建的控件,都是通过'绝对定位'的方式来设定的。也就是每个控件所在的位置,都需要计算坐标,最终通过 setGeometry 或者 move 方式摆放过去。这种方式虽然不错,但这种设定方式其实并不方便:

  • 手动布局非常复杂,而且不精确、并且无法对窗口的大小自适应
  • 尤其是界面如果内容比较多,不好计算
  • 而且一个窗口大小往往是可以调整的,按照绝对定位的方式,也无法自适应窗口大小

因此 Qt 引入'布局管理器'(Layout) 机制,来解决上述问题。当然,布局管理器并非 Qt 独有。其他的 GUI 开发框架,像 Android,前端等也有类似的机制。

Qt 中提供了很多种布局管理器:

  1. 垂直布局 (QVBoxLayout)
  2. 水平布局 (QHBoxLayout)
  3. 网格布局(行列)(QGridLayout)
  4. 表单布局 (QFormLayout)

垂直布局 QVBoxLayout

使用 QVBoxLayout 表示垂直的布局管理器(V 就是 vertical 的缩写)。

核心属性

属性说明
layoutLeftMargin左侧边距
layoutRightMargin右侧边距
layoutTopMargin上方边距
layoutBottomMargin下方边距
layoutSpacing相邻元素之间的间距

实操示例

  1. 目的:创建 3 个按钮,使用垂直布局管理器管理起来
  2. 创建三个按钮通过构造填写文本(布局管理器作为父元素,后续只需通过该布局管理器进行添加操作即可)
  3. 创建布局管理器对象
  4. 将三个按钮添加布局管理器中(addWidget),这样三个按钮以及布局管理器都是在对象树上的
  5. 将布局管理器设置到窗口上(setLayout)
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
#include <QVBoxLayout>

Widget::Widget(QWidget *parent) : QWidget(parent), ui( Ui::Widget)
{
    ui->();
    
    QPushButton* b1 =  ();
    QPushButton* b2 =  ();
    QPushButton* b3 =  ();
    
    QVBoxLayout* layout =  ();
    layout->(b1);
    layout->(b2);
    layout->(b3);
    ->(layout);
}

Widget::~()
{
     ui;
}
new
setupUi
this
// 创建三个按钮
new
QPushButton
"按钮 1"
new
QPushButton
"按钮 2"
new
QPushButton
"按钮 3"
new
QVBoxLayout
addWidget
addWidget
addWidget
this
setLayout
Widget
delete

此时拖拽窗口,按钮就会自适应窗口。

更多细节

  1. 注意:在代码中,当你调用 QWidget::setLayout() 时,只能设置一个布局管理器,但允许嵌套多个布局管理器。这个布局管理器会成为 Widget 的直接布局管理器。
  2. 在代码中创建多个 layout 时,它们会嵌套在第一个生成的 Layout 上。
    • layout 标签表示的是布局管理器的本体,外面会自动创建出了一个 Widget
    • 每个 layout 里面就可以包含若干个 item(也就是如按钮的控件)
  3. 也可以先拖拽其他控件,然后再套上 layout。

框选住刚刚拖拽的控件,然后点击左上角就能放到 layout 中。

水平布局 QHBoxLayout

使用 QHBoxLayout 表示水平的布局管理器(H 是 horizontal 的缩写)。

核心属性

(和 QVBoxLayout 属性是一致的)

属性说明
layoutLeftMargin左侧边距
layoutRightMargin右侧边距
layoutTopMargin上方边距
layoutBottomMargin下方边距
layoutSpacing相邻元素之间的间距

实操示例

  1. 创建出三个按钮,按钮 1/2/3
  2. 创建 QHBoxLayout 对象
  3. 将按钮添加到 layout 中(addWidget)
  4. 再将 layout 设置到 this 上(setLayout)
  5. 还能通过 layoutLeftMargin…等设置边距
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
#include <QHBoxLayout>

Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget)
{
    ui->setupUi(this);
    QPushButton* b1 = new QPushButton("按钮 1");
    QPushButton* b2 = new QPushButton("按钮 2");
    QPushButton* b3 = new QPushButton("按钮 3");
    
    // 创建一个 h 布局管理器
    QHBoxLayout* layout = new QHBoxLayout();
    // 将按钮添加到布局管理器中
    layout->addWidget(b1);
    layout->addWidget(b2);
    layout->addWidget(b3);
    setLayout(layout);
    layout->setMargin(200); // 边距
    layout->setSpacing(50); // 内部控件见的距离
}

Widget::~Widget()
{
    delete ui;
}

嵌套布局

布局管理器之间,也能嵌套布局管理器(例如:垂直布局内部嵌套水平布局)。

  1. 创建垂直布局管理器 QVBoxLayout 对象
  2. 设置到窗口里面:setLayout
  3. 添加两个按钮进去 addWidget
  4. 创建一个水平的布局管理器
    • 也添加两个按钮进去
  5. 把水平布局管理器添加到垂直布局管理器内部(addLayout)
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
#include <QVBoxLayout>
#include <QHBoxLayout>

Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget)
{
    ui->setupUi(this);
    QVBoxLayout* vLayout = new QVBoxLayout();
    this->setLayout(vLayout);
    
    QPushButton* b1 = new QPushButton("按钮 1");
    QPushButton* b2 = new QPushButton("按钮 2");
    
    // 创建一个 h 布局管理器
    QHBoxLayout* hLayout = new QHBoxLayout();
    // 将按钮添加到布局管理器中
    hLayout->addWidget(b1);
    hLayout->addWidget(b2);
    
    QPushButton* b4 = new QPushButton("按钮 4");
    QPushButton* b5 = new QPushButton("按钮 5");
    vLayout->addWidget(b4);
    vLayout->addWidget(b5);
    vLayout->addLayout(hLayout);
}

Widget::~Widget()
{
    delete ui;
}

网格布局 QGridLayout

Qt 中还提供了 QGridLayout 用来实现网格布局的效果。可以达到 M * N 的这种网格的效果。

核心属性

整体和 QVBoxLayout 以及 QHBoxLayout 相似。但是设置 spacing 的时候是按照垂直水平两个方向来设置的。

属性说明
layoutLeftMargin左侧边距
layoutRightMargin右侧边距
layoutTopMargin上方边距
layoutBottomMargin下方边距
layoutHorizontalSpacing相邻元素之间水平方向的间距
layoutVerticalSpacing相邻元素之间垂直方向的间距
layoutRowStretch行方向的拉伸系数
layoutColumnStretch列方向的拉伸系数

实操示例

  1. 创建 4 个按钮 按钮 1/2/3/4
  2. 创建一个 QGridLayout 网格布局对象
  3. 添加将按钮添加进去 addWidget,其中传递过程中还需要设置 行、列
  4. 将网格布局管理器设置到窗口中 setLayout
  5. 因为是行列的添加按钮的位置,所以可以随意的放到网格中
  6. 任意调整行列,即可看到不同的效果,但注意的是如果设置的是一个很大的值,但是这个值和上一个值之间并没有其他的元素,那么并不会在中间腾出额外的空间
  7. 此处设置的行数和列数,只是用来决定控件之间的相对位置,谁先谁后

甚至还可以斜着布局,同理放到同一列(就相当于垂直布局),将 4 个按钮都放到同一行(就相当于水平布局)。

#include "widget.h"
#include "ui_widget.h"
#include <QGridLayout>
#include <QPushButton>

Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget)
{
    ui->setupUi(this);
    // 创建 GridLayout 布局管理器
    QGridLayout* grid = new QGridLayout();
    
    // 创建 4 按按钮
    QPushButton* b1 = new QPushButton("按钮 1");
    QPushButton* b2 = new QPushButton("按钮 2");
    QPushButton* b3 = new QPushButton("按钮 3");
    QPushButton* b4 = new QPushButton("按钮 4");
    
    // 斜着布局
    grid->addWidget(b1, 0, 0);
    grid->addWidget(b2, 1, 1);
    grid->addWidget(b3, 2, 2);
    grid->addWidget(b4, 3, 3);
    
    setLayout(grid);
}

Widget::~Widget()
{
    delete ui;
}

拉伸系数

  1. 刚刚创建的布局管理器,里面控件的尺寸都是均等的
  2. 当需要创建出尺寸不同的是,就可以设置拉伸系数
  3. 拉伸系数就相当于设置控件之间尺寸的比例
实操
  1. 创建 6 个 按钮 1 ~ 6,使用网格布局 2 * 3 的方式排列
  2. 在设置水平拉伸系数 setColumnStretch:按照 1:1:2 的比例进行放置
  3. 当拉伸系数设为 0,就不参与拉伸,那么按钮的大小就是固定值
设置垂直拉伸系数的问题

当我们设置垂直拉伸系数,发现其实并没有效果。这是因为 QSizePolicy 的限制(默认是 Ignored 的):

QSizePolicy::Ignored : 忽略控件的尺寸,不对布局产生影响 QSizePolicy::Minimum : 控件的最小尺寸为固定值,布局时不会超过该值。 QSizePolicy::Maximum : 控件的最大尺寸为固定值,布局时不会小于该值。 QSizePolicy::Preferred : 控件的理想尺寸为固定值,布局时会尽量接近该值。 QSizePolicy::Expanding : 控件的尺寸可以根据空间调整,尽可能占据更多空间。 QSizePolicy::Shrinking : 控件的尺寸可以根据空间调整,尽可能缩小以适应空间

所以按钮设置 setSizePolicy 的尺寸策略为 QSizePolicy::Expanding,让其可以拉伸展开(需要同时设置垂直和水平)。这样就能完成垂直的策略。

// 将三列中比例为 1:1:3
ui->gridLayout->setColumnStretch(0, 1);
ui->gridLayout->setColumnStretch(1, 1);
ui->gridLayout->setColumnStretch(2, 3);

// 将行的比例为 1:3
ui->gridLayout->setRowStretch(0, 1);
ui->gridLayout->setRowStretch(1, 3);

// 设置策略
ui->pushButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
// ... 其他按钮同样设置

表单布局 QFormLayout

类似一种填表,填调查问卷的样式,一般是 N 行 2 列。

实操示例

  1. 设置 3 行 2 列的表单,并设置到窗口中
  2. 创建 3 个 label,并作为第一列
  3. 创建 3 个输入框作为第二列
  4. 将上述控件添加到表单中 addRow(Column1, Column2,...)(添加到行中)
  5. 创建一个提交按钮,并同样放到表单中
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
#include <QLineEdit>
#include <QFormLayout>
#include <QLabel>

Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget)
{
    ui->setupUi(this);
    // 创建 layout
    QFormLayout* layout = new QFormLayout();
    this->setLayout(layout);
    
    // 创建三个 label
    QLabel* label1 = new QLabel("姓名");
    QLabel* label2 = new QLabel("年龄");
    QLabel* label3 = new QLabel("电话");
    
    // 创建三个 lineEdit
    QLineEdit* lineEdit1 = new QLineEdit();
    QLineEdit* lineEdit2 = new QLineEdit();
    QLineEdit* lineEdit3 = new QLineEdit();
    
    // 创建一个提交按钮
    QPushButton* btn = new QPushButton("提交");
    
    // 把上述元素添加到 layout 中
    layout->addRow(label1, lineEdit1);
    layout->addRow(label2, lineEdit2);
    layout->addRow(label3, lineEdit3);
    layout->addRow(NULL, btn);
}

Widget::~Widget()
{
    delete ui;
}

Spacer 空白

使用布局管理器的时候,可能需要在控件之间,添加一段空白。就可以使用 QSpacerItem 来表示,通过添加这个控件来达到空白的效果。

核心属性

属性说明
width宽度
height高度
hData水平方向的 sizePolicy
vData垂直方向的 sizePolicy

实操

让两个按钮中间有一定的空白:

  1. 创建 QHBoxLayout,并设置到创建中
  2. 图按钮中间并没有空隙,现在想要让他空开一点:就可以使用 spacer 使两个按钮之间存在空白
  3. 通过 addSpacerItem 进行添加 spacer 控件
  4. QSpacerItem 构造的时候设置宽高

通过添加空间的顺序确定 spacer 的位置。若放到前面则空白在前,反之在后。

总结

前面的每个控件本质都是可扩展的,每个控件都是 Qt 内置的一个类,咱们在代码中都可以基于这个类,继承出自定义的子类,在这个自定义的子类中,又可以添加许多的属性和方法,实现自己的需求场景,还可以在子类中,把多个控价组合到一起。

目录

  1. Qt 布局管理器详解
  2. 布局管理器概述
  3. 垂直布局 QVBoxLayout
  4. 核心属性
  5. 实操示例
  6. 更多细节
  7. 水平布局 QHBoxLayout
  8. 核心属性
  9. 实操示例
  10. 嵌套布局
  11. 网格布局 QGridLayout
  12. 核心属性
  13. 实操示例
  14. 拉伸系数
  15. 实操
  16. 设置垂直拉伸系数的问题
  17. 表单布局 QFormLayout
  18. 实操示例
  19. Spacer 空白
  20. 核心属性
  21. 实操
  22. 总结

更多推荐文章

查看全部
  • 红黑树深入剖析及 Java 实现
  • MCP 插件配置指南:以 browser-tools-mcp 为例
  • ChatGPT 实用技巧:文本与数据的结构化方法解析
  • 宇树科技机器人核心技术
  • Python 布尔类型详解:真值规则与逻辑运算实战
  • 论文解读:利用人类反馈训练语言模型遵循指令
  • CSS 样式基础与界面布局实战指南
  • 百度文心大模型 4.5 开源测评:架构、部署与实战
  • 花生二手车交易平台全栈项目实战:Spring Boot 3 与 Vue 3 高并发架构
  • 基于 Clawdbot 与 Ollama 部署 Qwen3-32B 本地 AI 网关
  • 前端跨子域通讯实战:方案选型与避坑指南
  • JavaScript 集合 (Set、WeakSet) 与映射 (Map、WeakMap)
  • 字节跳动开源 Seed-OSS-36B:512K 上下文推理新突破
  • AI 大模型应用开发初探:基于 Semantic Kernel 构建简易 Agent
  • Python Django Web 框架实战:构建产品管理系统
  • 大模型基础面试知识全解析:架构、训练与微调策略
  • 2026 年:技术人如何用 AI 前瞻性思维应对职业变革
  • 注意力机制与 Transformer 模型架构及实战详解
  • 大模型时代:程序员转型 AI 的传统机器学习路径
  • 前端缓存策略实战:从本地存储到 Service Worker

相关免费在线工具

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online