QT图形界面开发
安装
进入网站
Download Qt OSS: Get Qt Online Installer
进入这个网站,一定要先注册,注册之后要打开邮箱做邮箱验证,然后才可以使用。
下载

选择正确的版本,点击按钮就自动下载了
切换镜像开启安装(重要)
下载完成之后一定要使用power shell打开下载文件所在的文件夹


然后输入
1
| .\ (连括号整个替换成下载下来的文件名) --mirror https://mirrors.ustc.edu.cn/qtproject/
|
然后就自动切换镜像并且开始了安装流程
如果你出现“无法将“.\qt-online-installer-windows-x64-4.8.0.exe”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。”这样的错误,那90%概率你替换有误
安装过程
输入账号密码开始安装,基本上一直点下一步就行
(懒得重新截图了,下面的几张图来自csdn 文章编号:132645054)




这里要选择安装路径(不能有中文)








等待安装完成就结束了安装。
创建项目
创建项目随便选一个,基于这里创建的类型不同可能会有不同,但是基本上差别不大。
后记:这里如果选第一个就是用C++的方式去编写程序,如果选第二个就是编写控制台程序
只有选第三个和第四个才是用QML编写程序

进去之后 直接点左下角运行一下

如果出现这个可以拖动的helloword就是创建成功了

代码学习(基于QML的方式)
认识QT
qt是一个图形框架,基于C++开发
可以做什么?
windows linux mac软件,安卓,ios,鸿蒙
qt两大派系
QML C++
QML的语法更加简单 适合没学过C++的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| import QtQuick
Window {
property int a property string str1 :"hello world QML"
width: 640 height: 480 visible: true title: str1
id:root Rectangle{ x:100 y:100 width:root.width/3 height:200 color:"blue"
Text{ x:20 y:100 text:"第二个文本" } }
Text{ text:"你好 123" }
}
|
笛卡尔坐标系

登陆界面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| import QtQuick import QtQuick.Controls
Window { property string str1:"登陆界面"
width: 320 height: 480 visible: true title: str1 id:root
Image{ id:redrabbit x:(root.width-redrabbit.width)/2 width:120 height:140 source: "https://spjblogimg-1329562662.cos.ap-shanghai.myqcloud.com/img/5eea8644b528184bef8380be5fb36de9.jpg" }
TextField{ x:30 y:200 width:250 height: 45 font.pixelSize: 20 verticalAlignment:Text.AlignVCenter horizontalAlignment: Text.AlignHCenter placeholderText: "请输入账号" }
TextField{ x:30 y:270 width:250 height: 45 font.pixelSize: 20 verticalAlignment:Text.AlignVCenter horizontalAlignment: Text.AlignHCenter placeholderText: "请输入密码 " echoMode: TextInput.Password }
Button{ x:30 y:350 width:250 height:50 text:"登录"
}
}
|
使用技巧(快捷键)

项目管理

Clang代码模型

QT框架功能概述
QT类库的模块
QT中的模块分为两大类
QT基本模块:提供了QT再所有平台上的基本功能
QT附加模块:实现一些特定功能的模块
基本模块

附加模块

QT附加模块可以实现一些特定目的,可能只在某些开发平台上有,或只能用于某些操作系统
QT全局定义
头文件(QT类的头文件都会包含该头文件)包含了QT类库的一些全局定义:
基本数据
函数
宏
数据类型定义:
确保再各个平台上都有同意确定的长度


全局函数定义

还有一些基础的数学原酸函数再头文件中定义,比如三角运算函数,弧度与角度之间的转换函数
宏定义


QT的元对象系统
QT中引入元对象系统堆标准C++语言进行了扩展
QObject类是所有使用原对象系统的类的基类
必须在一个类的开头部分插入宏Q_OBJECT,才可以使用元对象系统的特性。当MOC发现类中定义了Q_OBJECT宏时,会为其生成相应的C++源文件
元对象编译器是一个预处理器,先将Qt的特性程序转换为标准C++程序,再由标准C++编译器进行编译
Object类

QMetaObject类
元对象是对类的描述,包含类信息、方法、属性等元数据
QObject和QMetaObject 提供了以下函数接口,可以获取运行时类型信息,类似标准的C++中的RTTI

属性系统
在OObject的子类中可以通过Q_PROPERTY宏定义属性


这个部分后面太难了,学不懂,确定要用了再回来学
信号与槽
信号与槽是元对象系统支持的,对象间通信所采用的机制
connect函数的使用

其中第一个参数是发送者,第二个参数是信号,第三个参数是接收者,这样就可以读懂了。
可知接收者往往就是指针,另这个函数是静态函数,所以不管在哪里调用都行。
比如在widget里面使用,那么肯定是指向widget的(子类)
如果信号和槽函数都存在重载的情况,则需要使用qOverload<参数类型>进行指定:

上面的形式都是静态函数版本,无法获得对象本身的this指针。还有成员函数的版本
disconnect()函数的使用

sender()函数
在槽函数里,使用QObject::sender()可以获取信号发射者的指针
1
| QSPinBox*spinbox = qobject_cast<QSpinBox*>(sender())
|
自定义信号及其使用

代码学习(基于C++)
声明:此部分的学习过程严格遵循《QT6 C++开发指南 2023》

认识QT
简介:QT是一个跨平台的应用开发框架,也是最主流的C++开发框架
QT具有其他编程语言的拓展,但QT本身是用C++开发
跨平台
QT具有跨平台开发的的能力,只要熟悉一种平台的开发,很快就能适应其他平台的开发。并且QT源代码编译之后生成目标平台的原生二进制代码,不像JAVA那样需要虚拟机,运行效率更高。
QT支持的开发语言
C++和QML:
Q对标准的C+++语言进行了扩展,引入了信号和槽等机制。
QML是一个用来描述应用程序界面的声明式脚本语言
C++和QML可以混合使用
python:不做赘述
编写一个hello world程序
创建文件

这里就要选择第一个了,因为现在要用C++的方式编写
重点是下图的地方要选qmake或者cmake,要求是选qmake


上面是选择基类,基本上也这样选,之后如果没有特殊情况都这样构建新项目。
构建完程序之后进入下面的画面,其中点击.ui文件自动跳转到了Design界面去编辑界面,编辑的方式类似早期我学过的VB,大概了解到了,这个.ui文件就是对于窗口布局的描述说明。

再design里面找到label,然后拖到右边。

就可以在这里写上hello world了
在右下角的部分可以改变文字的属性,框体也可以直接用拖动的方式编辑。
点击左下角就可以直接运行,这样第一个程序就结束了。
GUI程序设计基础
GUI程序结构与运行机制

上面说了我们选择qmake的方式编写,这样一定会生成.pro结尾的配置文件,对于qmake中的配置文件有一些常见变量和含义(如下)

再来说一下这个pro文件中常见的+=语法和格式,相当于把右边的包中的内容加到左边,类似于C++中的包含头文件

qmake是构建项目的软件,它根据.pro文件生成makefile文件,然后C++编译器可以根据makefile文件进行编译和链接
qmake还会自动生成moc(meta-object compiler)和UIC(user interface compiler)生成构建规则
$$为替换函数的前缀
认识qt基础文件
pro文件在上面已经说了,剩下的几个文件我通过注释的方式大概了解一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| widget.h #ifndef WIDGET_H #define WIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACE
class Widget : public QWidget { Q_OBJECT
public: Widget(QWidget *parent = nullptr); ~Widget();
private: Ui::Widget *ui; }; #endif
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| main.cpp #include "widget.h"
#include <QApplication>
int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; w.show(); return a.exec(); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| widget.cpp #include "widget.h" #include "ui_widget.h"
Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { ui->setupUi(this); }
Widget::~Widget() { delete ui; }
|
更改窗口标题
在如下图右下角位置可以更改

信号与槽简介
信号与槽式QT编程的基础,也是QT的一大创新,它使QT中的组件就叫唤变得直观

上面式信号槽多种实现方式中的一种,connect式QObject类中的静态成员函数。signal和slot式QT的宏,用于将哟参数转换为相应的字符串。下面式一些注意事项:
一个信号可以连接多个槽函数
多个信号可以连接同一个参函数

一个型号可以连接另一个信号
QT还支持通过函数名称将信号和槽相关联,需要首先开启该功能。
QT项目构建过程的基本原理

实操部分
关闭程序
因为全部是实操涉及代码 ,所以只能由我来描述操作的过程。实际过程也没办法用视频展示。首先按照惯例新建一个项目,然后来到ui设计的部分。然后拖入一个label 拖入一个btn。
然后就来到了这部分的关键操作:在下面选择信号与槽,然后选择刚才加入的按钮对象,事件选择关闭,对象选择整个widget窗口,触发选择点击。
到这里为止关闭的功能就做好了,可以直接运行程序。

除此之外,关于修改按钮内容和标签内容,还可以通过代码的方式修改,在widget.cpp文件中使用this指针赋值就行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| #include "widget.h" #include "ui_widget.h"
Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { ui->setupUi(this); ui->label->setText("这是用代码修改的标签"); ui->pushButton->setText("代码修改"); }
Widget::~Widget() { delete ui; }
|

同时经过我自己的测试,代码修改的方式优先级比直接在设置里面修改高。
可视化UI设计
项目要求

注意 这个项目创建的时候必须要选择Qdialog作为窗口基类
比如我就做错了,所以下面的教程前面的部分都是根据错误的项目做的,但是步骤都是对的,只是中间我退回去重新构建了一下项目
加入qrc文件


成功导入之后进入设计页面,再右下角搜索icon,这个windowicon就是这个窗口左上角的图标了,然后通过右边的选择就可以选择刚才导入成功的bmp图标,然后再运行就会出现图中的样子,显示导入已经成功了,图标已经替换成了我们想要的图标。

接下来就可以设计ui了
ui设计大致如下,上面我们已经改了窗口的图标
然后这里的设计用了两个group box 来排版
然后字体部分用了check box 颜色部分是radio button
下面就是一个可以输入的input widgets 输入窗口 选择的是Plain Text Edit

构建好了基础的ui之后再为下方的三个按钮加上图标
首先选择要更改的按钮,点击之后在右下角搜索icon,然后通过选择的方式就可以选择到自己加入过的图标了。

这里我做到这这一步 才发现程序建立的时候建立错误了。我的程序不是基于Qdialog的 我用了widget
所以这里我退回去重做了
重新构建完了之后,先进去信号与槽,然后通过选择把退出按钮的功能实现
然后把确定按钮的功能暂定为accept()

接下来要做清空的功能,首先右键清空键,选择go to slot
然后选择clicked()


然后就进入了一个代码界面

然后通过手动的方式写功能,调用了一个clear函数

编写完了之后测试一下 功能正常
然后在来到字体部分,同样是右键点击。但是这里是要选择勾中和没勾中的状态,所以这里要选择布尔类型的clicked

同样也是通过代码的方式修改,这里可能有点困难,所以我把截图先放上来,最后把代码全部放上来。
简单来说就是通过上面的操作修改之后,再通过下面的代码实现功能 三个字体操作的代码基本上是一样的
只有调用的set方法不同

代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| #include "dialog.h" #include "ui_dialog.h"
Dialog::Dialog(QWidget *parent) : QDialog(parent) , ui(new Ui::Dialog) { ui->setupUi(this); }
Dialog::~Dialog() { delete ui; }
void Dialog::on_clearBtn_clicked() { ui->plainTextEdit->clear(); }
void Dialog::on_checkBox_clicked(bool checked) {
QFont font = ui->plainTextEdit->font(); font.setUnderline(checked); ui->plainTextEdit->setFont(font);
}
void Dialog::on_checkBox_3_clicked(bool checked) { QFont font = ui->plainTextEdit->font(); font.setItalic(checked); ui->plainTextEdit->setFont(font); }
void Dialog::on_checkBox_2_clicked(bool checked) { QFont font = ui->plainTextEdit->font(); font.setBold(checked); ui->plainTextEdit->setFont(font);
}
|
到这里为止 字体的部分已经全部设置好了,功能已经全部实现了。
接下来是关于颜色的部分,颜色是单选框 然后需要发送给同样的slots
说人话就是要手写代码了:首先来到头文件
首先在头文件里创建一个slot函数(注意slot函数的返回值类型都是void
然后再右键 去定义

来到cpp文件的部分完成这里的代码 发现没有起作用

说人话就是这里相当于只是写了一个函数,但是没有被调用,没有被加在主程序中,所以没有效果。
所以还要在上面的基类中加入connect
那么问题来了,怎么写这个connect语句
首先我们来到文件的顶部
然后点击上面自动生成的ui头文件

在里面第一个函数结束前上方就可以找到

然后我们手动添加connect就成功了

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
| dialog.cpp #include "dialog.h" #include "ui_dialog.h"
Dialog::Dialog(QWidget *parent) : QDialog(parent) , ui(new Ui::Dialog) { ui->setupUi(this); connect(ui->blackRad,SIGNAL(clicked()), this, SLOT(do_FontColor())); connect(ui->blueRad,SIGNAL(clicked()), this, SLOT(do_FontColor())); connect(ui->redRad,SIGNAL(clicked()), this, SLOT(do_FontColor())); }
Dialog::~Dialog() { delete ui; }
void Dialog::on_clearBtn_clicked() { ui->plainTextEdit->clear(); }
void Dialog::on_checkBox_clicked(bool checked) {
QFont font = ui->plainTextEdit->font(); font.setUnderline(checked); ui->plainTextEdit->setFont(font);
}
void Dialog::on_checkBox_3_clicked(bool checked) { QFont font = ui->plainTextEdit->font(); font.setItalic(checked); ui->plainTextEdit->setFont(font); }
void Dialog::on_checkBox_2_clicked(bool checked) { QFont font = ui->plainTextEdit->font(); font.setBold(checked); ui->plainTextEdit->setFont(font);
}
void Dialog::do_FontColor() { QPalette plet = ui->plainTextEdit->palette();
if(ui->blackRad->isChecked()) plet.setColor(QPalette::Text,Qt::black); if(ui->redRad->isChecked()) plet.setColor(QPalette::Text,Qt::red); if(ui->blueRad->isChecked()) plet.setColor(QPalette::Text,Qt::blue); ui->plainTextEdit->setPalette(plet); }
dialog.h #ifndef DIALOG_H #define DIALOG_H
#include <QDialog>
QT_BEGIN_NAMESPACE namespace Ui { class Dialog; } QT_END_NAMESPACE
class Dialog : public QDialog { Q_OBJECT
public: Dialog(QWidget *parent = nullptr); ~Dialog();
private slots: void on_clearBtn_clicked();
void on_checkBox_clicked(bool checked);
void on_checkBox_3_clicked(bool checked);
void on_checkBox_2_clicked(bool checked); void do_FontColor();
private: Ui::Dialog *ui; }; #endif
|
小结一下:上面主要讲了通过可视化UI设计(反正就是创建项目的时候选择genarate form,就是可视化ui设计了)来进行设计qt程序。第一步是创建程序,这个不赘述,第二部是设计UI,包括导入我们自己的图标等。第三步是给完成各个功能,主要通过代码的方式,操作底层逻辑暂时都学的差不多了,但是如何操作其他的还是不清楚。
代码化UI设计

要求和上面的可视化UI设计一样,不同的是不勾选generate form,所以没有很多东西
说是更灵活,但是对我来说也更难。
cpp文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
| #include "dialog.h"
#include <QHBoxLayout> #include <QVBoxLayout>
#include <QCheckBox> #include <QRadioButton> #include <QPlainTextEdit> #include <QPushButton>
void Dialog::do_chkBoxUnder(bool checked) { QFont font = txtEdit->font(); font.setUnderline(checked); txtEdit->setFont(font); }
void Dialog::do_chkBoxItalic(bool checked) { QFont font = txtEdit->font(); font.setItalic(checked); txtEdit->setFont(font); }
void Dialog::do_chkBoxBold(bool checked) { QFont font = txtEdit->font(); font.setBold(checked); txtEdit->setFont(font); }
void Dialog::do_setFontColor() { QPalette plet=txtEdit->palette(); if(radioBlack->isChecked()) plet.setColor(QPalette::Text,Qt::black); if(radioRed->isChecked()) plet.setColor(QPalette::Text,Qt::red); if(radioBlue->isChecked()) plet.setColor(QPalette::Text,Qt::blue); txtEdit->setPalette(plet); }
Dialog::Dialog(QWidget *parent) : QDialog(parent) { chkBoxUnder = new QCheckBox("下划线"); chkBoxBold = new QCheckBox("加粗"); chkBoxItalic = new QCheckBox("斜体"); QHBoxLayout *HLayl = new QHBoxLayout(); HLayl->addWidget(chkBoxUnder); HLayl->addWidget(chkBoxItalic); HLayl->addWidget(chkBoxBold);
radioBlack = new QRadioButton("黑色"); radioRed = new QRadioButton("红色"); radioBlue = new QRadioButton("蓝色"); QHBoxLayout *HLayl2 = new QHBoxLayout(); HLayl2->addWidget(radioBlack); HLayl2->addWidget(radioRed); HLayl2->addWidget(radioBlue); QVBoxLayout *Vlayl = new QVBoxLayout();
txtEdit = new QPlainTextEdit; txtEdit ->setPlainText("hello world \n 手工创建!"); QFont font = txtEdit->font(); font.setPointSize(20); txtEdit->setFont(font);
btn0k = new QPushButton("确定"); btnCancel = new QPushButton("取消"); btnClose = new QPushButton("退出"); QHBoxLayout *HLayl3 = new QHBoxLayout(); HLayl3->addStretch(); HLayl3 ->addWidget(btn0k); HLayl3->addStretch(); HLayl3 ->addWidget(btnCancel); HLayl3->addStretch(); HLayl3 ->addWidget(btnClose);
Vlayl->addLayout(HLayl); Vlayl->addLayout(HLayl2); Vlayl->addWidget(txtEdit); Vlayl->addLayout(HLayl3);
setLayout(Vlayl);
connect(chkBoxUnder,SIGNAL(clicked(bool)),this,SLOT(do_chkBoxUnder(bool))); connect(chkBoxItalic,SIGNAL(clicked(bool)),this,SLOT(do_chkBoxItalic(bool))); connect(chkBoxBold,SIGNAL(clicked(bool)),this,SLOT(do_chkBoxBold(bool))); connect(radioBlack,SIGNAL(clicked(bool)),this,SLOT(do_setFontColor())); connect(radioBlue,SIGNAL(clicked(bool)),this,SLOT(do_setFontColor())); connect(radioRed,SIGNAL(clicked(bool)),this,SLOT(do_setFontColor())); connect(btn0k,SIGNAL(clicked()),this,SLOT(accept())); connect(btnCancel,SIGNAL(clicked()),this,SLOT(reject())); connect(btnClose,SIGNAL(clicked()),this,SLOT(close()));
setWindowTitle("手工打造UI");
}
Dialog::~Dialog() {}
|
头文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| #ifndef DIALOG_H #define DIALOG_H #include <QDialog>
class QCheckBox; class QRadioButton; class QPlainTextEdit; class QPushButton;
class Dialog : public QDialog { Q_OBJECT private: QCheckBox *chkBoxUnder; QCheckBox *chkBoxItalic; QCheckBox *chkBoxBold;
QRadioButton *radioBlack; QRadioButton *radioRed; QRadioButton *radioBlue;
QPlainTextEdit *txtEdit;
QPushButton *btn0k; QPushButton *btnCancel; QPushButton *btnClose;
private slots: void do_chkBoxUnder(bool checked); void do_chkBoxItalic(bool checked); void do_chkBoxBold(bool checked);
void do_setFontColor();
public: Dialog(QWidget *parent = nullptr); ~Dialog(); }; #endif
|
使用cmake构建系统
使用cmake构建系统(其他所有示例都使用qmake构建系统)
cmake是一个功能强大的跨平台的构建工具,它通过与平台和编译器无关的配置文件控制软件的构建过程(在不同的平台上使用不同的编译器),生成本地化的makefile文件或者IDE项目。很多大型的开源软件都使用cmake构建系统,qt6本身就是用cmake构建的。
本章节任务就是使用cmake实现上节课实现的。cmake项目是用cmake语言写的一些文件,项目的主文件是cmakeLists.txt
新建项目,这部分不赘述,容易错的点就是要选dialog
构建完了之后找到之间建立的qmake项目,把项目中的这四个部分覆盖到现在新建的cmake项目。

然后修改一下ui的文字,重新保存,修改一下头文件,重新保存。(如果不修改,编译器不会判定为文件改变,不会保存也不会重新编译。)
然后在配置文件里面加上下面一行。

然后重新保存,ui图标和功能就全部正常了
下面的部分是使用cmakeGUI生成VS工程,我认为用不到就先不学了,如果要用再回来学。
学习路线2
从按钮入手认识QT和样式
创建文件的过程不赘述,以下是按钮的mainwindow.cpp文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| #include "mainwindow.h" #include "ui_mainwindow.h" #include <QPushButton>
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow)
{ ui->setupUi(this);
QPushButton * button = new QPushButton("01",this);
button->setGeometry(50,50,150,100);
button->setStyleSheet("color:red;" "background-color:lightblue;" "font-size:30px;");
button->setFlat(false);
button->setVisible(true);
}
MainWindow::~MainWindow() { delete ui; }
|
槽函数和lambda表达式
在上节课中我们已经建立了按钮,但是这个按钮并没有任何的功能,这节课通过槽函数我们就要给这个按钮赋予功能。
现在我们要给按钮赋予功能,现在以点击弹出提示框为例。
槽函数是 Qt 框架中用于处理信号(signal)和响应(响应事件)的核心机制之一。它是 Qt 中事件驱动编程的一部分,用于处理控件或其他对象触发的事件。
什么是槽函数?
槽函数是普通的成员函数或独立的函数,当某个信号发出时,槽函数会被调用。它们与 Qt 的信号-槽机制紧密结合,负责响应来自对象(如按钮、窗口等)发出的信号。
作用:
槽函数的主要作用是响应信号。它们使得 Qt 的对象可以根据特定事件或操作触发后执行某些操作。信号和槽提供了一种松耦合的机制,可以轻松实现不同对象之间的通信,而不需要彼此直接依赖。
Lambda 表达式(也称为匿名函数)是一种在 C++11 引入的语法,用于创建没有名字的内联函数。它允许你在代码的某个地方定义一个函数,并将其传递或直接使用,而无需先声明或定义一个完整的函数。
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
| #include "mainwindow.h" #include "ui_mainwindow.h" #include <QPushButton>
#include <QMessageBox>
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow)
{ ui->setupUi(this);
QPushButton * button = new QPushButton("01",this);
button->setGeometry(50,50,150,100);
button->setStyleSheet("color:red;" "background-color:lightblue;" "font-size:30px;");
button->setFlat(false);
button->setVisible(true);
connect(button,&QPushButton::clicked,[]{ QMessageBox::information(nullptr,"提示","你点击了按钮"); });
}
MainWindow::~MainWindow() { delete ui; }
|
垂直布局和水平布局
为什么需要一个中心部件?
QMainWindow 是 Qt 中用于构建主窗口的类,它具有许多预定义的区域(例如,菜单栏、工具栏、状态栏等),但是它没有一个默认的区域来放置你自己的控件。因此,你需要设置一个“中心部件”(central widget),作为显示控件的容器。
具体的原因
- QMainWindow 的布局限制:
QMainWindow 自带了许多特殊的区域(例如菜单、工具栏、状态栏等),但是它本身没有提供直接用于添加控件的区域。你必须设置一个“中心部件”来填充主窗口的中央区域。
- 中心部件的作用:
中心部件可以是任何 QWidget 类型的控件,布局管理器(如 QVBoxLayout 或 QHBoxLayout)会被应用到这个中心部件上,这样布局管理器中的控件就会显示在主窗口的中央区域。
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| #include "mainwindow.h" #include "ui_mainwindow.h" #include <QPushButton> #include<QVBoxLayout> #include<QHBoxLayout>
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); QWidget * centralWidget01 = new QWidget(this); setCentralWidget(centralWidget01);
QHBoxLayout * hBoxLayout01 = new QHBoxLayout();
QPushButton * button01 = new QPushButton("按钮1",this); QPushButton * button02 = new QPushButton("按钮2",this); QPushButton * button03 = new QPushButton("按钮3",this); button01->setFixedSize(100,50); button02->setFixedSize(100,50); button03->setFixedSize(100,50);
hBoxLayout01->addWidget(button01); hBoxLayout01->addWidget(button02); hBoxLayout01->addWidget(button03);
centralWidget01->setLayout(hBoxLayout01);
}
MainWindow::~MainWindow() { delete ui; }
|
微调框
QSpinBox
QSpinBox是QT框架中用于输入整数的微调框控件。用于可以通过点击微调框旁边的上下箭头来增加或者减少整数值,也可以直接在输入框中输入整数。它提供了设置了最小、最大值和步长的功能。
QDoubleSpinBox
和上面的类似,但他用于输入浮点数。用户可以通过上下箭头或者直接输入来改变值,再上述功能的基础上还提供了小数位数的功能。
常用方法
QSpinBox
setMinimum(int min):设置微调框的最小值。
setMaxIum(int max):设置最大值
setSingleStep(int step):设置每次点击上下箭头时数值的变化量
setValue(int value):设置微调框的当前值。
value():获取微调框的当前值。
QDoubleSpinBox
setMinimum(double min):设置微调框的最小值。
setMaxIum(double max):设置最大值
setSingleStep(double step):设置每次点击上下箭头时数值的变化量
setValue(double value):设置微调框的当前值。
value():获取微调框的当前值。
setDecimals(int prec):设置小数位数
在头文件中声明私有成员变量的好处:
- 可以使得类的接口完整,类的使用者能够直接访问类中的控件和布局。
- 遵循封装原则,类的实现细节可以隐藏在
.cpp 文件中,提供清晰的接口。
- 可以方便其他类、模块和源文件与
MainWindow 类交互和调用这些成员。
配置OpenCV的方法!!!
自用版
因为跑起来问题非常的多,而且复杂,但是通过种种原因终于是成功引用了。
首先对于一个项目
点击这里添加库

选择外部库

选择这个
然后下面这个选项选择这个build

导入成功之后会有这样的两段话

把上面的换成绝对路径,把下面的换成加上include就行了
大作业开发
软件设计报告
一、软件设计任务概述
应用背景
随着计算机视觉和人工智能技术的快速发展,图像与视频处理软件在各个领域得到了广泛应用。例如,在医学影像分析、安防监控、工业检测以及娱乐应用中,图像与视频处理技术发挥着重要作用。本项目旨在开发一款功能全面、界面友好的图像与视频处理软件,支持基本的图像处理操作、视频处理功能以及基于深度学习的智能视觉分析。
任务目标
- 实现基本的图像处理功能,包括灰度化、二值化、均值模糊、伽马校正和边缘检测。
- 支持视频处理功能,包括视频播放、暂停、快进、快退以及马赛克处理。
- 集成基于YOLO的物体检测功能,实现对图像和视频中的目标检测。
- 实现人脸检测功能,增强软件的智能性。
- 提供友好的用户界面,使用户能够方便地操作和配置各项功能。
开发环境搭建
- 操作系统:Windows 10 或更高版本。
- 开发工具:Qt Creator 6.0 或更高版本。
- 第三方库:OpenCV 4.5.0 或更高版本,用于图像和视频处理;
dnn模块用于YOLO模型的加载与推理。
- 其他依赖:C++编译环境(如MSVC)。
二、可行性研究、需求分析及进度规划
可行性研究
- 技术可行性:
- OpenCV和Qt提供了强大的图像和视频处理功能,能够满足项目需求。
- YOLO模型在目标检测领域性能优越,且推理速度快,适合集成到实时处理中。
- 人脸检测可以通过OpenCV自带的.CascadeClassifier实现,技术成熟。
- 经济可行性:
- 项目主要依赖开源库,无需额外购买许可证或付费服务,开发成本较低。
- 仅需基本的硬件设备(如普通PC),无需高端服务器或专用设备。
- 操作可行性:
- 软件界面设计直观,用户无需专业培训即可上手。
- 功能模块化设计,用户可以根据需求选择性使用功能。
需求分析
用户需求
:
- 专业用户(如研究人员、开发者)需要强大的图像处理和分析功能。
- 普通用户(如摄影师、爱好者)需要简单易用的图像编辑工具。
功能需求
:
- 基本图像处理功能(灰度化、二值化等)。
- 视频播放与处理功能。
- 智能视觉分析功能(目标检测、人脸检测)。
进度规划
| 阶段 |
时间 |
描述 |
| 需求分析与设计 |
1周 |
确定功能需求,设计软件架构,完成UI设计。 |
| 开发阶段 |
3周 |
实现图像处理功能,集成OpenCV和YOLO模块,开发视频处理功能。 |
| 测试与优化 |
1周 |
测试各功能模块,修复bug,优化性能。 |
| 文档撰写与总结 |
1周 |
撰写软件设计报告,整理测试记录与开发心得。 |
三、软件设计的基本原理和采用的主要方法与技术
基本原理
- 图像处理:
- 基于OpenCV库实现图像的读取、显示和处理。
- 使用滑块控件(QSlider)实现参数调节(如亮度、对比度)。
- 视频处理:
- 使用OpenCV的VideoCapture类实现视频的读取与播放。
- 通过QTimer实现视频的实时显示与处理。
- AI智能视觉:
- 使用YOLO目标检测模型实现图像和视频中的目标检测。
- 通过dnn模块加载预训练模型,进行实时推理。
- 人脸检测:
- 使用OpenCV的.CascadeClassifier实现人脸检测。
- 通过滑块控件调节检测灵敏度。
主要方法与技术
- 模块化设计:
- 将功能模块化,如图像处理、视频处理、AI检测等,便于管理和维护。
- MVC模式:
- 模型(Model):数据存储与处理。
- 视图(View):用户界面展示。
- 控制器(Controller):处理用户输入与功能调用。
- 异步处理:
- 使用QTimer和信号槽实现视频的实时处理,避免主线程阻塞。
四、实现的过程与步骤
实现流程
- 需求分析与设计
- 确定功能模块,设计软件架构。
- 完成UI设计,使用Qt Designer绘制界面。
- 开发阶段
- 实现图像处理功能(灰度化、二值化等)。
- 集成OpenCV和dnn模块,实现YOLO目标检测。
- 开发视频处理功能,包括播放、暂停、快进、快退。
- 测试与优化
- 测试各功能模块,修复bug。
- 优化性能,提升处理速度。
框图
1 2 3 4 5 6 7 8 9 10 11 12 13
| +-------------------+ +-------------------+ | | | | | 用户界面 |<----->| 控制器 | | | | | +-------------------+ +-------------------+ | | | | v v +-------------------+ +-------------------+ | | | | | 模型(数据) | | 视图(展示) | | | | | +-------------------+ +-------------------+
|
功能模块流程图
图像处理流程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| 用户点击“打开图片”按钮 | v 读取并加载图片 | v 显示原始图片 | v 用户选择滤镜(如灰度化、二值化等) | v 应用滤镜并处理图片 | v 更新并显示处理后的图片
|
视频处理流程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| 用户点击“打开视频”按钮 | v 加载视频文件或摄像头流 | v 显示视频第一帧 | v 用户点击“播放”按钮 | v 启动视频播放定时器 | v 循环处理并显示视频帧 | v 用户点击“暂停”或“停止”按钮 | v 停止视频播放并更新界面状态
|
AI检测流程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| 用户点击“初始化YOLO”按钮 | v 加载YOLO模型和分类名称 | v 用户点击“开始检测”按钮 | v 循环处理视频或图像帧 | v 应用YOLO检测并标记目标 | v 更新并显示检测结果
|
整体流程图
1 2 3 4 5 6 7 8 9 10 11 12 13
| +-------------------+ +-------------------+ | | | | | 用户界面 |<----->| 控制器 | | | | | +-------------------+ +-------------------+ | | | | v v +-------------------+ +-------------------+ | | | | | 模型(数据) | | 视图(展示) | | | | | +-------------------+ +-------------------+
|
详细步骤说明
- 用户交互
- 数据加载
- 根据用户选择,加载图片或视频文件,或开启摄像头流。
- 功能处理
- 根据选择的功能模块,调用相应的处理函数(如图像滤镜、视频播放、目标检测)。
- 数据处理
- 对加载的数据进行处理,如应用滤镜、检测目标、调整参数等。
- 结果展示
- 状态反馈
五、遇到的困难与获得的主要成果
遇到的困难
- 技术难点
- YOLO模型的加载与推理速度优化。
- 实时视频处理中多线程的协调与同步。
- 时间压力
- 项目时间紧张,需要在短时间内完成多个功能模块的开发与测试。
- 资源限制
- 由于硬件性能限制,YOLO模型的推理速度较慢,影响了用户体验。
获得的主要成果
- 成功实现了基本的图像处理功能,包括灰度化、二值化、均值模糊等。
- 集成并优化了YOLO目标检测功能,实现了对图像和视频的实时检测。
- 实现了视频的播放与处理功能,用户可以自由控制视频的播放速度与方向。
- 成功实现了人脸检测功能,增强了软件的智能性。
六、测试与运行记录
测试环境
- 操作系统:Windows 10
- 硬件配置:Intel i7处理器,16GB内存,NVIDIA GeForce GTX 1060
- 软件版本:Qt 6.0,OpenCV 4.5.0
测试用例
- 图像处理功能
- 打开一张图片,应用灰度化、二值化等滤镜,检查处理效果。
- 使用滑块调节亮度和对比度,观察图像变化。
- 视频处理功能
- 打开一段视频,播放、暂停、快进、快退,检查控制是否正常。
- 应用马赛克处理,检查视频画质是否受到影响。
- AI检测功能
- 打开一张图片,应用YOLO目标检测,检查检测结果。
- 打开一段视频,应用YOLO目标检测,检查实时检测效果。
测试结果
- 图像处理功能:运行正常,处理效果符合预期。
- 视频处理功能:运行流畅,控制响应灵敏。
- AI检测功能:检测准确率较高,但在复杂场景下可能误检。
测试截图
(以下为部分测试截图,展示了图像处理和目标检测的效果。)

图1:灰度化处理效果

图2:二值化处理效果

图3:YOLO目标检测效果
七、结果分析
功能实现
- 软件成功实现了所有预设功能,包括图像处理、视频处理和AI检测。
- 用户界面设计直观,操作简便,适合各类用户使用。
性能优化
- 通过多线程和异步处理,提升了视频处理的流畅度。
- YOLO模型的推理速度在硬件性能允许的范围内得到了优化。
用户体验
- 软件运行稳定,功能切换流畅,用户反馈良好。
- AI检测功能增强了软件的智能化,提升了用户体验。
不足与改进
- 在复杂场景下,YOLO的检测精度可能不足,需要优化模型或使用更先进的算法。
- 视频处理功能在低配置硬件上运行较慢,需要进一步优化代码性能。
八、软件开发心得
回顾整个开发过程,我深刻体会到软件开发的不易。从最初的代码敲击到功能的逐步完善,每一个环节都充满了挑战。尤其是在集成YOLO模型和优化视频处理性能的过程中,我经历了无数次的调试和优化,甚至在深夜里仍然在思考如何解决技术难题。
尽管开发过程中充满了困难,但最终的成功让我感到无比的成就感。通过这个项目,我不仅提升了自己的技术水平,还学会了如何在有限的时间内高效地解决问题。软件开发不仅仅是代码的堆砌,更是一种艺术,需要耐心、毅力和创造力。
这次开发经历让我明白,每一个功能的实现都离不开细致的思考和反复的测试。未来的开发中,我将继续保持这种严谨的态度,不断提升自己的技术水平,为用户带来更好的使用体验。

QT学习止步于此 再见了 的所有 QT福音战士
其他
关于bmp文件
看到视频教程里面用了很多的bmp文件,很多插入的文件也是bmp
但是因为没有花钱买原课程,只能蹭蹭免费的,所以这个问题需要我自己解决。
首先我找了阿里的图标库
iconfont-阿里巴巴矢量图标库
然后在里面找了几套适合的下载jpeg或者jpg格式,然后通过在线工具进行转换,得到了一套可以用的bmp格式的图标文件。
注意导入的时候需要在项目文件内部建一个文件夹,然后再在文件夹内放入图片,选择项目外部的文件夹进行导入报错了。
如何导入?
两种方法进行导入 第一种方法通过代码,修改pro文件,加入,这种方法不知道为什么失败了。
第二种方法 直接查看目录中的《加入qrc文件》部分即可