auther: abinng date: 2026-03-26 10:01
createDate:2026-03-26 10:01
在银行等私密输入密码的地方,其键盘的排列并不是顺序的123456789,而是九个位置顺序打乱
功能描述
矩阵键盘分为数字键(0~9),功能按键(删除和确认)
输入 6 位数字模拟密码,每次输入 6
位后,键盘数字按键随机变换坐标,功能按键坐标固定
点击确定后,显示清零后数字按键随机变换坐标
矩阵键盘按键尺寸固定,每个按键长宽为 80px * 80px,LCD
显示区长宽为 240px * 80px
创建项目
本次使用 CLion ,如果还没安装:CLion
安装
进入 CLion -> New Project -> (左侧)Qt Widget Executable
修改项目路径
选择 Qt CMake prefix path 其实就是 CMakeLists.txt 中的
set(CMAKE_PREFIX_PATH "D:/09_SW/_Dev/Qt/6.5.3/mingw_64")
Language stand ...
auther: abinng date: 2026-03-21 11:29
createDate:2026-03-21 11:29
信号和槽的连接
上一篇我们学过了 Qt 的元对象系统,就是为了信号和槽做铺垫
信号和槽的作用是什么呢?
实现 Qt 的对象之间通信、解耦
信号和槽的实现:
设计信号、槽函数
关联信号和槽函数
在一个合适的位置发射信号
怎么将信号和槽关联起来呢?
1234// 字符串形式:QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection)// 没有接收者形式:QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal, Functor functo ...
auther: abinng date: 2026-03-20 22:53
createDate:2026-03-20 22:53
本篇主要了解即可,初学时不深入了解也行
引入
Qt 的元对象使用特性
类中写 Q_OBJECT 宏
继承 QObject
不能放到 cpp 文件中
前两个的效果就可以理解成,普通的类结构外扩了一部分,就叫做元对象,就是一个空间,包含结构信息
而我们的 Qt Core 要解析这部分外扩的结构,需要一个API接口(Qt
已经实现好的),所以其中的结构也要按照 Qt 要求的结构实现
原来的那一部分就不需要解析,这是我们自己定义的成员
那为什么不能放到 cpp 文件中呢?
类的定义肯定是在 .h 文件中,对应的函数实现在 .cpp 中,API
接口就可以调用函数实现,来提取这部分外扩的结构信息。这部分函数实现也是
Qt 生成的
之前了解过 UIC 和 RCC
UIC:将 UI 文件转换成 .h 文件,会被打包到可执行文件中
RCC:将资源文件打包成 cpp 文件,会被打包到可执行文件中
而现在这个元对象系统可以称为 ...
auther: abinng date: 2026-03-20 21:05
createDate:2026-03-20 21:05
前言
Qt5 中是 QRandom 类,Qt6 中是
QRandomGenerator 类
在计算机中,随机数的生成本质上是基于初始‘种子’的复杂数学计算。如果种子固定,生成的随机数序列就是可预测的。
为了生成高质量、安全的随机数,现代操作系统会在底层收集硬件噪音、外部输入等物理混沌现象建立
‘熵池 (Entropy Pool)’ ,Qt
通常会结合操作系统底层的‘熵池’来自动获取极其随机的初始种子。
固定种子
我们用 QRandomGenerator
类的实例对象生成一些固定种子的随机数,打印试试
1234567891011#include <QRandomGenerator>#include <QDebug>int main() { QRandomGenerator *gen = new QRandomGenerator(1); for (int i = 0; i < 9; ++i) { ...
auther: abinng date: 2026-03-20 11:19
createDate:2026-03-20 11:18
是什么
具体展示出来的话就是,可以调整左右/上下比例的分割,如下图:
鼠标放在分割线上时,会变成这个图标,拖动就可以调整左右比例,你肯定见过
这个比例调整也分情况,一种是可以完全将左边/右边拖没,另一种是拖到一定程度,分割条就不会再往该方向动了
打开 UI 设计器,发现 splitter 有一个
childrenCollapsible 的属性
写一个仿 IDE 的布局
实现以下的 UI :
123456789101112131415161718void Widget::myshow4() { // 设置窗口大小 this->setGeometry(50, 100, 450, 400); // 主布局 auto *main_layout = new QHBoxLayout(this); // 分割器1, 左右分割 auto *main_splitter = new QSplitter( ...
auther: abinng date: 2026-03-19 15:51
createDate:2026-03-19 15:51
常用布局
QHBoxLayout:水平布局 QVBoxLayout:垂直布局 QGridLayout:网格布局
QFormLayout:表单布局
代码实践
0. 说明一下
这里我们要写代码了,先清晰一下结构
我们在 QtCreator 中创建了 QWidget
程序后,会有四个主要文件:main.cpp, widget.h, widget.cpp, widget.ui
当我们用鼠标点的方式设计了 widget.ui
时,还会临时生成一个 ui_widget.h ,在
widget.cpp 中的构造函数内部有一个
ui->setupUi 用 Ctrl + 左键
的方式就可以定位到 ui_widget.h 中
首先 main.cpp 中:
12345678910#include "widget.h"#include <QApplication>int main(int argc, char *argv[]){ ...
auther: abinng date: 2026-03-19 14:28
createDate:2026-03-19 14:28
基本容器
Qt6 中大致分为两类容器:顺序容器、关联容器
注意没有链式容器,因为:
现代 CPU 的算力极快,但内存读取很慢。CPU
极其依赖连续内存带来的“预取(Prefetching)”红利。QList
这种指针跳跃式的内存布局,导致 Cache Miss 率极高,性能其实很差。
Qt6 中,QList 和 QVector
合并了,根据官方手册,QVector 现在是 QList
的一个别名.
如果想用链式容器,还是使用 stl 中的 list 吧
顺序容器:QVector, QList,
QStack, QQueue 关联容器:QMap,
QMultiMap, QSet, QHash,
QMultiHash
遍历方式
迭代器风格
123begin(), end()cbegin(), cend()rbegin(), rend()
1234567891011121314// 1. 顺序容器 QList, QVec ...
auther: abinng date: 2026-03-18 211:03
createDate:2026-03-18 21:03
从字符编码讲起
计算机字符编码起源于英语系国家,初始是 ASCII 编码,实现了 128
个符号的映射关系
但是后来非英语国家也对字符编码有需求,显然 ASCII 的 8bit
不够表示那么多状态,不够那么多映射关系,此时依旧沿用低 7
位标识英语系符号,使用多字节来进行编码,有了国标码,例如中国是 GBK
而后肯定有一个问题是,在中国使用 GBK
编码的文件,发送到了阿拉伯国家,编码格式变了,数据翻译成了另外的含义,不便于传输信息
所以有了 Unicode 编码,2Byte 表示所有符号,是一个统一符号编码。当然
2Byte 还是不太够,因为还有 emoji
表情等符号,后面还有其他编码,这里暂且不论
but, 英语系国家原本只用到了低 7 位的二进制,现在要使用 Unicode
编码就得数据长度翻倍且效果一致,这是定长编码的缺点。那就用变长编码(梦回哈夫曼编码…),用字符出现的概率对不同的字符进行长度适应,出现概率大的字符 ...
auther: abinng date: 2026-03-18 19:52
createDate:2026-03-18 19:51
主要逻辑
Qt
控件都会有一个父对象指针,依附于一个父对象,一旦父对象释放,父对象所有的子对象都会被自动析构,如下图:
当任何一个
QObject(不管是父是子)被销毁(调用析构函数)时,它会自动做两件事:
向下看(作为父对象):
遍历自己的子对象列表(Children List),对里面所有的子对象执行
delete 操作。
向上看(作为子对象): 通过 parent
指针找到自己的父对象,告诉父对象:“我要死了,请把我从你的子对象列表中移除掉。”(如果不做这一步,父对象以后析构时就会
delete 一个野指针导致崩溃)。
所以,无论你是手动 delete
了一个子对象,还是父对象被销毁引发了连锁反应,Qt
的这套机制都能保证内存安全。
在栈上创建对象时,会有释放顺序,如果先释放了父对象,再释放子对象,就会导致子对象多次释放,出错。所以一般会最上层的控件定义在栈上,下面管理的子控件申请在堆上
测试代码
12 ...
auther: abinng date: 2026-03-18 20:07
createDate:2026-03-18 20:07
在传统的 C++ 编译过程的基础上,多出了三个部分:
ui 文件
元对象系统—>信号和槽相关
QRC 资源文件
Qt 程序的标准编译流程
在标准的 C++ 编译流程(预处理 -> 编译 -> 汇编 ->
链接)之前,Qt 增加了一个非常关键的 “代码生成阶段”
。整个过程可以分为以下五个核心步骤:
1. 界面文件的处理 (UIC - User Interface
Compiler)
输入: 开发者在 UI 设计器(Qt
Designer)中拖拽生成的界面文件,比如 win.ui(本质上是一个
XML 格式的文件)。
处理: Qt 提供的 UIC 工具
会解析这个 .ui 文件,并自动生成标准的 C++ 头文件,例如
ui_win.h。
关联: 我们的业务逻辑代码(如
win.cpp)通过 #include "ui_win.h"
来获取并操控界面上的控件。(图中标注的
win. ...










