【Qt】如何优雅的进行界面布局

文章目录

  • 1 :peach:写在前面:peach:
  • 2 :peach:垂直布局:peach:
  • 3 :peach:水平布局:peach:
  • 4 :peach:网格布局:peach:
  • 5 :peach:表单布局:peach:


1 🍑写在前面🍑

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

这种设定⽅式其实并不⽅便,尤其是界⾯如果内容⽐较多, 不好计算。⽽且⼀个窗⼝⼤⼩往往是可以调整的, 按照绝对定位的⽅式, 也⽆法⾃适应窗⼝⼤⼩。因此 Qt 引⼊ 布局管理器 (Layout) 机制, 来解决上述问题。


2 🍑垂直布局🍑

使⽤ QVBoxLayout 表⽰垂直的布局管理器,V 是 vertical 的缩写。

核⼼属性:

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

Layout 只是⽤于界⾯布局, 并没有提供信号。

代码示例:

Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QPushButton* btn1 = new QPushButton("按钮1");QPushButton* btn2 = new QPushButton("按钮2");QPushButton* btn3 = new QPushButton("按钮3");// 创建布局管理器, 并且把按钮添加进去// 如果创建的时候指定⽗元素为 this, 则后⾯不需要 setLayout ⽅法QVBoxLayout* layout = new QVBoxLayout();layout->addWidget(btn1);layout->addWidget(btn2);layout->addWidget(btn3);// 把布局管理器设置到 widget 中this->setLayout(layout);
}

验证结果:
在这里插入图片描述
使用代码的方式时我们拖拽窗口时,按钮的位置也会随着窗口的调整而改变。

我们还可以使用图形化界面的方式来进行垂直布局:
在这里插入图片描述
但是注意使用图形化界面的方式时我们拖拽窗口,按钮的位置不会随着窗口的调整而改变。


3 🍑水平布局🍑

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

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

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

代码⽰例:

Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QPushButton* btn1 = new QPushButton("按钮1");QPushButton* btn2 = new QPushButton("按钮2");QPushButton* btn3 = new QPushButton("按钮3");// 创建布局管理器QHBoxLayout* layout = new QHBoxLayout();layout->addWidget(btn1);layout->addWidget(btn2);layout->addWidget(btn3);// 设置 layout 到 widget 上this->setLayout(layout);
}

结果验证:
在这里插入图片描述

同理我们也可以使用图形化界面的方式来创建水平布局。这里就不再演示了。


4 🍑网格布局🍑

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

核⼼属性:整体和 QVBoxLayout 以及 QHBoxLayout 相似,但是设置 spacing 的时候是按照垂直⽔平两个⽅向来设置的。

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

代码⽰例:

Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 创建 4 个按钮QPushButton* btn1 = new QPushButton("按钮1");QPushButton* btn2 = new QPushButton("按钮2");QPushButton* btn3 = new QPushButton("按钮3");QPushButton* btn4 = new QPushButton("按钮4");// 创建⽹格布局管理器, 并且添加元素QGridLayout* layout = new QGridLayout();layout->addWidget(btn1, 0, 0);layout->addWidget(btn2, 0, 2);layout->addWidget(btn3, 1, 1);layout->addWidget(btn4, 1, 3);// 设置 layout 到窗⼝中.this->setLayout(layout);
}

结果验证:
在这里插入图片描述
我们再来看看使用下面的代码会出现什么情况:

Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 创建 4 个按钮QPushButton* btn1 = new QPushButton("按钮1");QPushButton* btn2 = new QPushButton("按钮2");QPushButton* btn3 = new QPushButton("按钮3");QPushButton* btn4 = new QPushButton("按钮4");// 创建⽹格布局管理器, 并且添加元素QGridLayout* layout = new QGridLayout();layout->addWidget(btn1, 0, 0);layout->addWidget(btn2, 1, 0);layout->addWidget(btn3, 2, 0);layout->addWidget(btn4, 5, 0);// 设置 layout 到窗⼝中.this->setLayout(layout);
}

结果验证:
在这里插入图片描述
此处也要注意, 设置⾏和列的时候, 如果设置的是⼀个很⼤的值, 但是这个值和上⼀个值之间并没有其他的元素, 那么并不会在中间腾出额外的空间。

代码⽰例: 设置 QGridLayout 中元素的⼤⼩⽐例

Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 创建 6 个按钮QPushButton* btn1 = new QPushButton("按钮1");QPushButton* btn2 = new QPushButton("按钮2");QPushButton* btn3 = new QPushButton("按钮3");QPushButton* btn4 = new QPushButton("按钮4");QPushButton* btn5 = new QPushButton("按钮5");QPushButton* btn6 = new QPushButton("按钮6");// 创建⽹格布局管理器, 并且添加元素QGridLayout* layout = new QGridLayout();layout->addWidget(btn1, 0, 0);layout->addWidget(btn2, 0, 1);layout->addWidget(btn3, 0, 2);layout->addWidget(btn4, 1, 0);layout->addWidget(btn5, 1, 1);layout->addWidget(btn6, 1, 2);// 设置拉伸⽐例,设置为0的话为默认大小// 第 0 列拉伸⽐例设为 3;layout->setColumnStretch(0, 3);// 第 1 列拉伸⽐例设为 2,layout->setColumnStretch(1, 2);// 第 2 列拉伸⽐例设为 1layout->setColumnStretch(2, 1);// 设置 layout 到窗⼝中.this->setLayout(layout);
}

结果验证:
在这里插入图片描述

另外, QGridLayout 也提供了 setRowStretch 设置⾏之间的拉伸系数。上述案例中, 直接设置 setRowStretch 效果不明显, 因为每个按钮的⾼度是固定的,需要把按钮的垂直⽅向的 sizePolicy 属性设置为 QSizePolicy::Expanding 尽可能填充满布局管理器, 才能看到效果。

代码⽰例: 设置垂直⽅向的拉伸系数。

使⽤ setSizePolicy 设置按钮的尺⼨策略,可选的值如下:

  • QSizePolicy::Ignored : 忽略控件的尺⼨,不对布局产⽣影响。
  • QSizePolicy::Minimum : 控件的最⼩尺⼨为固定值,布局时不会超过该值。
  • QSizePolicy::Maximum : 控件的最⼤尺⼨为固定值,布局时不会⼩于该值。
  • QSizePolicy::Preferred : 控件的理想尺⼨为固定值,布局时会尽量接近该值。
  • QSizePolicy::Expanding : 控件的尺⼨可以根据空间调整,尽可能占据更多空间。
  • QSizePolicy::Shrinking : 控件的尺⼨可以根据空间调整,尽可能缩⼩以适应空间。
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 创建 6 个按钮QPushButton* btn1 = new QPushButton("按钮1");QPushButton* btn2 = new QPushButton("按钮2");QPushButton* btn3 = new QPushButton("按钮3");QPushButton* btn4 = new QPushButton("按钮4");QPushButton* btn5 = new QPushButton("按钮5");QPushButton* btn6 = new QPushButton("按钮6");// 设置按钮的 sizePolicy, 此时按钮的⽔平⽅向和垂直⽅向都会尽量舒展开btn1->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);btn2->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);btn3->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);btn4->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);btn5->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);btn6->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);// 创建⽹格布局管理器, 并且添加元素QGridLayout* layout = new QGridLayout();layout->addWidget(btn1, 0, 0);layout->addWidget(btn2, 0, 1);layout->addWidget(btn3, 1, 0);layout->addWidget(btn4, 1, 1);layout->addWidget(btn5, 2, 0);layout->addWidget(btn6, 2, 1);// 设置拉伸⽐例// 第 0 ⾏拉伸⽐例设为 1;layout->setRowStretch(0, 1);// 第 1 ⾏拉伸⽐例设为 0, 即为固定⼤⼩, 不参与拉伸layout->setRowStretch(1, 0);// 第 2 ⾏拉伸⽐例设为 2, 即为第 2 ⾏的宽度是第 0 ⾏的 2 倍layout->setRowStretch(2, 2);// 设置 layout 到窗⼝中.this->setLayout(layout);
}

结果验证:
在这里插入图片描述


5 🍑表单布局🍑

除了上述的布局管理器之外, Qt 还提供了 QFormLayout , 属于是 QGridLayout 的特殊情况, 专⻔⽤于实现两列表单的布局。这种表单布局多⽤于让⽤⼾填写信息的场景,左侧列为提⽰, 右侧列为输⼊框。

代码示例:

Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 创建 layoutQFormLayout* layout = new QFormLayout();this->setLayout(layout);// 创建三个 labelQLabel* label1 = new QLabel("姓名");QLabel* label2 = new QLabel("年龄");QLabel* label3 = new QLabel("电话");// 创建三个 lineEditQLineEdit* 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);}

结果验证:
在这里插入图片描述


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/14031.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

kubenetes中K8S的命名空间状态异常强制删除Terminating的ns

查看ns状态为异常: 查看ns为monitoring的状态为Termingating状态 使用方法一: kubectl delete ns monitoring --force --grace-period0 使用方法二: kubectl get ns monitoring -o json > monitoring.json 修改删除文件中的"kubern…

Oracle行迁移解析

行迁移(Row Migration)是Oracle数据库中的另一个现象,它与行链接类似,都是由于数据行大小的变化导致的存储问题,但其本质和影响有所不同。 触发条件:行迁移发生在当一个已存在的、原先能够完全存储在一个数…

Redis优化笔记

Redis优化 一:Key: 1.1.Key的规范: 测试如下: 1.2.拒绝BigKey: 我们可以用: MEMORY USAGE name命令来看它的大小。 注意,这里的第二种之所以不使用Keys *,因为在实际生产时&#…

强化学习算法

从上图看出,强化学习可以分成价值/策略、随机策略/确定策略、在线策略/离线策略、蒙特卡洛/时间差分这四个维度。这里分析了基础算法中除了在线策略/离线策略以外的其他维度。 (一)基础知识 一、基础概念 重点概念:状态S、动作A、…

leetcode题目16

最接近的三数之和 中等 给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数,使它们的和与 target 最接近。 返回这三个数的和。 假定每组输入只存在恰好一个解。 示例 1: 输入:nums [-1,2,1,-4], targ…

Android:使用Kotlin搭建MVC架构模式

一、简介Android MVC架构模式 M 层 model ,负责处理数据,例如网络请求、数据变化 V 层 对应的是布局 C 层 Controller, 对应的是Activity,处理业务逻辑,包含V层的事情,还会做其他的事情,导致 ac…

切换分支报错:Untracked Files Prevent Checkout

切换分支报错:Untracked Files Prevent Checkout 分支切换 Untracked Files Prevent Checkout 新起的项目在切换master分支到工作分支时,出现下图的问题: Untracked Files Prevent Checkout Move or commit them before checkout 网上的解决…

回溯算法05(leetcode491/46/47)

参考资料: https://programmercarl.com/0491.%E9%80%92%E5%A2%9E%E5%AD%90%E5%BA%8F%E5%88%97.html 491. 非递减子序列 题目描述: 给你一个整数数组 nums ,找出并返回所有该数组中不同的递增子序列,递增子序列中 至少有两个元素…

大数据智慧消防解决方案(24页PPT)

方案介绍: 大数据智慧消防解决方案是提升消防安全管理水平、保障人民群众生命财产安全的重要手段。通过集成物联网、云计算、大数据、人工智能等先进技术,构建集监测、预警、指挥、救援于一体的智慧消防系统,将为消防安全事业注入新的活力。…

工业级3D开发引擎HOOPS:创新与效率的融合!

在当今这个技术日新月异的时代,3D技术已成为推动各行各业发展的重要力量。从工程设计到游戏开发,从虚拟现实到增强现实,3D技术的应用无处不在,它极大地丰富了我们的生活和工作。而在这样的背景下,HOOPS作为一个强大的3…

vue watch深度监听数组每一项的变化

在 Vue 中,watch 选项默认只能监听对象的属性变化,无法直接监听数组的变化 监听数组变化 一般情况下我们监听数组变化,可以监听长度的变化 watch(() > list.value.length, (now, old) > {// 会在数组长度变化时触发 })上面的写法不能…

面试被问到sizeof的概念

面试被问到sizeof的概念 问题1: 定义一个空的类型 ,里面没有任何成员函数,和成员变量,对该类型求sizeof ,得到的结果是多少? 问题2: 如果在该类型中添加一个构造函数和析构函数呢? 问题3:如果将析构函数标记为虚函数呢? 解答: struct student{}; struct student stu; s…

爬虫技术升级:如何结合DrissionPage和Auth代理插件实现数据采集

背景/引言 在大数据时代,网络爬虫技术已经成为数据收集的重要手段之一。爬虫技术可以自动化地从互联网上收集数据,节省大量人力和时间成本。然而,当使用需要身份验证的代理服务器时,许多现有的爬虫框架并不直接支持代理认证。这就…

CSS动画技术(css-animation)

掌握CSS动画技术 一、CSS动画基础 1. 什么是CSS动画? CSS动画是一种在网页上创建动态效果的技术,通过CSS样式规则来实现元素的平滑过渡和变换。CSS动画通过改变属性值来控制元素的动态外观,如位置、大小、颜色、透明度等。 2. CSS动画与传…

mongoDB初体验

概念 NOSQL not only SQL 文档型数据库,按列存储,分布式架构,批量写入性能好 教程学习札记 db.getCollection("111").find({"name":"Jane"}) 关联关系设计 Example1 引用关系 {"_id":ObjectId(&q…

测试自动生成目录

目录 1,标题一 2,标题二 3,标题三 4,怎么做到的 1,标题一 内容11111111111111111111 2,标题二 内容22222222222222222 3,标题三 内容3333333333333333333 4,怎么做到的

递增链表去重

题目描述: 题目思路: 1.链表内的val是递增的,所以相同的值只会连续重复地出现。 2.设置三个指针: ①指向头结点指针,用于返回链表 ②指向返回链表链尾的指针,用于在新链表添加结点 ③遍历旧链表结点的…

C++ | Leetcode C++题解之第107题二叉树的层序遍历II

题目&#xff1a; 题解&#xff1a; class Solution { public:vector<vector<int>> levelOrderBottom(TreeNode* root) {auto levelOrder vector<vector<int>>();if (!root) {return levelOrder;}queue<TreeNode*> q;q.push(root);while (!q.e…

Redis实践—全国地址信息缓存

一、背景 在涉及全国地址的应用中&#xff0c;地址信息通常被频繁地查询和使用&#xff0c;例如电商平台、物流系统等。为了提高系统性能和减少对数据库的访问压力&#xff0c;可以使用缓存来存储常用的地址信息&#xff0c;其中 Redis 是一个非常流行的选择。 本次在一个企业入…

tomcat关不掉解决方案

改造tomcat的脚本,增加强制关闭tomcat进程. 找到tomcat安装目录&#xff08;如&#xff1a;/data/b2b/b2b_erp02/apache-tomcat-8.5.82/bin&#xff09;&#xff0c;在该目录下有个catalina.sh脚本&#xff0c;在脚本的上面添加一行 CATALINA_PID/data/b2b/b2b_erp02/apache-t…