【C++ Qt】布局管理器(QVBoxLayout、QHBoxLayout、QGridLayout、QFormLayout)

【C++ Qt】布局管理器(QVBoxLayout、QHBoxLayout、QGridLayout、QFormLayout)

每日激励:“不设限和自我肯定的心态:I can do all things。 — Stephen Curry”
🤔绪论​:
在Qt开发中,界面布局的合理设计是提升用户体验的关键。早期,开发者常采用绝对定位的方式摆放控件,即通过计算坐标并使用setGeometry或move方法逐一定位。然而,这种方法不仅复杂且不精确,难以适应窗口大小的变化,尤其在界面内容繁杂时,计算难度显著增加。
为解决这一问题,Qt引入了布局管理器机制,通过QVBoxLayout(垂直布局)、QHBoxLayout(水平布局)、QGridLayout(网格布局)和QFormLayout(表单布局)等工具,实现了控件的自动排列与窗口大小的自适应调整。布局管理器不仅简化了界面设计流程,还提高了布局的灵活性和可维护性,成为Qt开发中不可或缺的一部分。本文将详细介绍这些布局管理器的使用方法与技巧,助力开发者高效构建Qt界面。
————————
早关注不迷路🎠,话不多说安全带系好,发车啦(建议电脑🖥️观看)。

🐱‍🐉布局管理器

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

  • 手动布局非常复杂,而且不精确、并且无法对窗口的大小自适应
  • 尤其是界⾯如果内容⽐较多, 不好计算
  • ⽽且⼀个窗⼝⼤⼩往往是可以调整的, 按照绝对定位的⽅式, 也⽆法⾃适应窗⼝⼤⼩。
  • 因此 Qt 引⼊ “布局管理器” (Layout) 机制, 来解决上述问题.

当然,布局管理器并非 Qt 独有。其他的 GUI 开发框架,像 Android,前端等也有类似的机制。

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

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

⛰️垂直布局 QVBoxLayout

使⽤ QVBoxLayout 表⽰垂直的布局管理器(V 就是 vertical 的缩写)

核⼼属性🎈

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

实操1📄

  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(new Ui::Widget){ ui->setupUi(this);//创建三个按钮 QPushButton* b1 =newQPushButton("按钮1"); QPushButton* b2 =newQPushButton("按钮2"); QPushButton* b3 =newQPushButton("按钮3"); QVBoxLayout* layout =newQVBoxLayout(); layout->addWidget(b1); layout->addWidget(b2); layout->addWidget(b3);this->setLayout(layout);}Widget::~Widget(){delete ui;}

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

在这里插入图片描述

更多细节🔥

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

框选住刚刚拖拽的控件,然后点击再左上角(如下图)就能放到layout中

在这里插入图片描述

水🌊平布局 QHBoxLayout

使⽤ QHBoxLayout 表⽰垂直的布局管理器(H 是 horizontal 的缩写)

核⼼属性 🎈
(和 QVBoxLayout 属性是⼀致的)

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

实操1📄

  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<QVBoxLayout>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");// QVBoxLayout* layout = new QVBoxLayout();// layout->addWidget(b1);// layout->addWidget(b2);// layout->addWidget(b3);// this->setLayout(layout); QPushButton* b1 =newQPushButton("按钮1"); QPushButton* b2 =newQPushButton("按钮2"); QPushButton* b3 =newQPushButton("按钮3");//创建一个v布局管理器 QHBoxLayout* layout =newQHBoxLayout();//将按钮添加到布局管理器中 layout->addWidget(b1); layout->addWidget(b2); layout->addWidget(b3);setLayout(layout); layout->setMargin(200);//边距 layout->setSpacing(50);//内部控件见的距离}Widget::~Widget(){delete ui;}

实操2 🗒️

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

在这里插入图片描述
  1. 创建垂直布局管理器 QVBoxLayout对象
  2. 设置到窗口里面:setLayout
  3. 添加两个按钮进去addWidget
  4. 创建一个水平的布局管理
    1. 也添加两个按钮进去
  5. 把水平布局管理器添加到垂直布局管理器内部(addLayout)
#include"widget.h"#include"ui_widget.h"#include<QPushButton>#include<QVBoxLayout>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"); QVBoxLayout* vLayout =newQVBoxLayout();this->setLayout(vLayout); QPushButton* b1 =newQPushButton("按钮1"); QPushButton* b2 =newQPushButton("按钮2");//创建一个v布局管理器 QHBoxLayout* hLayout =newQHBoxLayout();//将按钮添加到布局管理器中 hLayout->addWidget(b1); hLayout->addWidget(b2); QPushButton* b4 =newQPushButton("按钮4"); QPushButton* b5 =newQPushButton("按钮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 🗒️

  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 =newQGridLayout();//创建4按按钮 QPushButton* b1 =newQPushButton("按钮1"); QPushButton* b2 =newQPushButton("按钮2"); QPushButton* b3 =newQPushButton("按钮3"); QPushButton* b4 =newQPushButton("按钮4");//水平布局// grid->addWidget(b1,0,0);// grid->addWidget(b2,0,1);// grid->addWidget(b3,0,2);// grid->addWidget(b4,0,3);// //垂直布局// grid->addWidget(b1,0,0);// grid->addWidget(b2,1,0);// grid->addWidget(b3,2,0);// grid->addWidget(b4,3,0);//斜着布局 grid->addWidget(b1,0,0); grid->addWidget(b2,1,1); grid->addWidget(b3,2,2); grid->addWidget(b4,3,300);setLayout(grid);}Widget::~Widget(){delete ui;}

了解下拉伸系数🍜:

  1. 刚刚创建的布局管理器,里面控件的尺寸都是均等的
  2. 当需要创建出尺寸不同的是,就可以设置拉伸系数
  3. 拉伸系数就相当于设置控件之间尺寸的比例

实操:

在这里插入图片描述
  1. 创建 6个 按钮1 ~ 6,使用网格布局 2 * 3 的方式排列(ui拖拽)
    在设置水平拉伸系数

setColumnStretch:按照1:1:2的比例进行放置

在这里插入图片描述

当拉伸系数设为设为0,就不参与拉伸,那么按钮的大小就是固定值

设置垂直⛰️拉伸系数的问题

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

QSizePolicy::Ignored : 忽略控件的尺⼨,不对布局产⽣影响QSizePolicy::Minimum : 控件的最⼩尺⼨为固定值,布局时不会超过该值。QSizePolicy::Maximum : 控件的最⼤尺⼨为固定值,布局时不会⼩于该值。QSizePolicy::Preferred : 控件的理想尺⼨为固定值,布局时会尽量接近该值。QSizePolicy::Expanding: 控件的尺⼨可以根据空间调整,尽可能占据更多空间。QSizePolicy::Shrinking : 控件的尺⼨可以根据空间调整,尽可能缩⼩以适应空间
  1. 所以按钮设置 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);//将行列的延展设置为自动扩展 ui->pushButton_2->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);//将行列的延展设置为自动扩展 ui->pushButton_3->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);//将行列的延展设置为自动扩展 ui->pushButton_4->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);//将行列的延展设置为自动扩展 ui->pushButton_5->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);//将行列的延展设置为自动扩展 ui->pushButton_6->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);//将行列的延展设置为自动扩展
在这里插入图片描述

表⌚单布局 QFormLayout

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

直接上实操:

  1. 设置3行2列的表单,并设置到窗口中
  2. 创建3个label,并作为第一列
  3. 创建3个输入框作为第二列
  4. 将上述控件添加到表单中addRow(Column1,Column2,...)(添加到行中)

创建一个提交按钮,并同样放到表单中

在这里插入图片描述
#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 =newQFormLayout();this->setLayout(layout);// 创建三个 label QLabel* label1 =newQLabel("姓名"); QLabel* label2 =newQLabel("年龄"); QLabel* label3 =newQLabel("电话");// 创建三个 lineEdit QLineEdit* lineEdit1 =newQLineEdit(); QLineEdit* lineEdit2 =newQLineEdit(); QLineEdit* lineEdit3 =newQLineEdit();// 创建⼀个提交按钮 QPushButton* btn =newQPushButton("提交");// 把上述元素添加到 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
• QSizePolicy::Ignored : 忽略控件的尺⼨,不对布局产⽣影响。
• QSizePolicy::Minimum : 控件的最⼩尺⼨为固定值,布局时不会超过该值。
• QSizePolicy::Maximum : 控件的最⼤尺⼨为固定值,布局时不会⼩于该值。
• QSizePolicy::Preferred : 控件的理想尺⼨为固定值,布局时会尽量接近该值。
• QSizePolicy::Expanding : 控件的尺⼨可以根据空间调整,尽可能占据更多空间。
• QSizePolicy::Shrinking : 控件的尺⼨可以根据空间调整,尽可能缩⼩以适应空间。
vData垂直⽅向的 sizePolicy 选项同上

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

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

通过添加空间的顺序确定spacer的位置

在这里插入图片描述


若放到前面则:

在这里插入图片描述

创建两个按钮,并添加到水平布局中
默认情况如下:

在这里插入图片描述

当然在ui文件中也是有的:

小总结🪢:

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


本章完。预知后事如何,暂听下回分解。

如果有任何问题欢迎讨论哈!

如果觉得这篇文章对你有所帮助的话点点赞吧!

持续更新大量C++ Qt细致内容,早关注不迷路。

Read more

【Python】unstructured 库:处理和预处理非结构化数据(如 PDF、Word 文档、HTML、图片等),转换为结构化格式

unstructured 是一个 Python 开源库,设计用于处理和预处理非结构化数据(如 PDF、Word 文档、HTML、图片等),将其转换为结构化格式,方便下游机器学习(ML)或大语言模型(LLM)任务。它提供模块化的组件(称为“bricks”),支持文档分区、清理和格式化,广泛应用于数据管道、RAG(Retrieval-Augmented Generation)系统和文档分析。 以下是对 unstructured 库的详细介绍,包括其功能、用法和实际应用,结合近期信息(截至 2025)。 1. unstructured 库的作用 * 非结构化数据处理:将复杂文档(如 PDF、DOCX、HTML)拆分为结构化元素(如标题、段落、列表、表格)。 * 模块化设计:

By Ne0inhk
库博(CoBOT):嵌入式 C/C++ 代码质量的全流程守护者 —— 从合规校验到漏洞根绝的国产化解决方案

库博(CoBOT):嵌入式 C/C++ 代码质量的全流程守护者 —— 从合规校验到漏洞根绝的国产化解决方案

在嵌入式系统领域,C/C++ 代码作为底层开发的核心载体,其质量直接决定设备的可靠性、安全性与合规性——无论是汽车电子的实时控制单元、工业装备的底层驱动程序、固件,还是军工装备的核心算法模块,一行代码的缺陷都可能引发系统崩溃、功能失效,甚至危及生命财产安全。当前嵌入式C/C++开发面临三大核心痛点: 1. 合规门槛高:军工、汽车等领域需严格遵循GJB、MISRA 等强制标准,人工校验成本高、漏检率高,难以满足高安全等级要求; 2. 缺陷隐蔽性强:缓冲区溢出、数组越界、空指针解引用等典型缺陷,在资源受限的嵌入式环境中易触发致命故障,且传统工具难以深度识别; 3. 国产化刚需迫切:关键领域需摆脱国外工具依赖,实现代码检测全流程自主可控,保障供应链安全。 库博(CoBOT)作为100%国产化的嵌入式C/C++静态代码分析工具,深度适配嵌入式场景特性,以 “标准全覆盖、缺陷深检测、环境高兼容” 为核心优势,构建从编码规范校验到安全漏洞根绝的全流程质量保障体系,

By Ne0inhk

Dear ImGui零基础集成指南:快速构建轻量级C++用户界面 [特殊字符]

Dear ImGui零基础集成指南:快速构建轻量级C++用户界面 🚀 【免费下载链接】imguiDear ImGui: Bloat-free Graphical User interface for C++ with minimal dependencies 项目地址: https://gitcode.com/GitHub_Trending/im/imgui Dear ImGui是一个轻量级、无膨胀的C++图形用户界面库,专为快速迭代和内容创作工具而设计。如果你正在寻找一个简单易用、功能强大的C++ GUI解决方案,这篇完整指南将带你从零开始掌握Dear ImGui集成技巧。 为什么选择Dear ImGui?✨ Dear ImGui的核心优势在于其极简主义设计和卓越的性能表现。与传统的保留模式GUI不同,它采用即时模式(Immediate Mode)范式,这意味着: * 无需状态同步 - 减少代码复杂性和潜在错误 * 最小化UI状态存储 - 让你的代码更简洁

By Ne0inhk

C++ CSV解析终极指南:快速处理大型CSV文件的高效解决方案

C++ CSV解析终极指南:快速处理大型CSV文件的高效解决方案 【免费下载链接】csv-parserA modern C++ library for reading, writing, and analyzing CSV (and similar) files. 项目地址: https://gitcode.com/gh_mirrors/csv/csv-parser 在处理现代数据分析和应用开发时,CSV解析和C++数据处理已成为不可或缺的核心技能。面对日益增长的大型文件处理需求,传统的文本处理方法往往力不从心。csv-parser作为一款专为C++设计的现代CSV解析库,通过内存映射IO和高效算法,让开发者能够轻松应对GB级数据文件,为数据密集型应用提供强有力的支持。 为什么你需要专业的CSV解析工具? 你是否曾经遇到过这些问题?🤔 * 处理几GB的CSV文件时程序频繁崩溃 * 不同来源的CSV文件格式各异,难以统一处理 * 内存使用失控,简单的数据读取却消耗大量系统资源 * 类型转换错误导致数据精度丢失 * 需要为每个项目重复编写CSV解析代码 这些痛点正

By Ne0inhk