【工程规范】
1 文件夹规范
每个核心模块代码放一个文件夹(方便 类版本迭代!)
-Yolo
--v1
---pri
---Yolo.pro
---yolo.h
---yolo.cpp
---Debug
项目文件夹
-Projects.pro
-debug
-module
--Yolo
--Halcon
-src
--yolo
---best.onnx
最终版本的pro
$$PWD表示 .pro所在文件夹
HEDERS += $$PWD/module/Yolo/v1/yolo.h
SOURCEs += $$PWD/module/Yolo/v1/yolo.cpp
每个pri
不管这个pri在哪里,所有地方直接include 头文件名字
注意:所有头文件名字唯一
INCLUDEPATH +=$$PWD
HEADERS += \
$$PWD/mainwindow.h
SOURCES += \
$$PWD/mainwindow.cpp
FORMS += \
$$PWD/mainwindow.ui
2 类规范
全部是QMainwindos类
可以使用qt和C++的全部功能
命名规范
- 类 *p_yolo
- 变量 a_
- 函数 DetectAndPass
(一)类套类
核心要义:面向对象编程
1. 1几十个Qt类
(pri嵌套大法)
1. 按照你要的模块建立文件夹
2. 对应的文件夹里面写一个.pri
3. pro文件包含这个pri
4. pri可以多级嵌套,从而实现模块嵌套
如下图
pri文件写法
1.2类嵌套如何实现?
(一个类成为另一个类的成员变量即可,注意this)
所有类都是qt ui界面类(方便使用this指针实现父子关系,方便一起析构,你只要不调用show方法,ui文件不会有影响)
例如,如何将B作为类A的成员:
#include<B.h>
class A
{
B* p_b=NULL;
}
void run()
{
p_b=new B(this);
p_b->setAttribute(Qt::WA_DeleteOnClose); //确保同时析构
}
1.3 一个类作为一个类的变量(this),怎么实现值传递?
目前是:A成员有个B,B成员有个C
1.3.1 C访问B,A
//c.cpp
#include "b.h"
#include "ui_b.h"
#include "a.h"
#include "ui_a.h"
//只能在cpp里面include!!
void C::on_pushButton_2_clicked()
{
B *pbwin=(B *) parentWidget(); //定义一个指向B的指针
int tmp1=pbwin->bnum;
cout<<"bnum "<<tmp1<<endl;
}
void C::on_pushButton_3_clicked()
{
A *pawin=(A *) parentWidget()->parentWidget();
int tmp2=pawin->anum;
cout<<"anum "<<tmp2<<endl;
}
1.3.2 A访问B,C
void A::show_c()
{
int tmp =this->pb->pc->cnum;
cout<<"cnum "<<tmp<<endl;
}
(二)多线程
步骤:
- 写好一个类,发现类里面有个函数比较复杂,需要多线程
- 类里使用lamda表达式创建一个关于该函数的线程,用的时候调用,然后detach即可
detach的理解:
1.detach后的线程谁也管不了了,他会一直运行,直到执行完代码。
2.所以这里的要注意有没有死循环,注意给他flag,让他退出循环,从而他可以执行完代码然后结束线程。
2.1 第一种情况::你只是执行一个会一路到底不会循环的耗时函数
void run()
{
do complicate work;
}
std::thread t()
{
return std::thread([=]{run();});
}
//开始启动多线程工作
void start()
{
std::thread th=t();
th.detach();
}
2.2 第二种情况:你要运行一个while(1)循环,不断做某事
由于detach是孤儿线程,你要定义一个flag,告诉它是时候退出while循环了,
那么跳出while循环后,他会执行完下面的代码,执行完了,这个线程就自动结束了
例如关闭一个mainwindow窗口,会发送一个qcloseevent消息
void closeEvent(QCloseEvent *event)
{
qDebug()<<"close event!!";
close_flag=1;
}
你的while循环根据这个close_flag来退出循环
(三)类之间传递数据
3.1 全局变量(放弃)
能不用就不用,就一司马玩意!!
所有.h文件里写:
extern std::string msg;
某一个.cpp文件里写:
std::string msg;
所有引用了这个头文件的cpp文件里就都可以使用msg这个全局变量了。
亲测:全局Mat有bug
3.2 parent指针
见 1.3
3.3 自定义消息变量
1 每一个类带一个自定义消息
2 每一个类带一个槽函数
3 利用emit signal slot机制传递数据
四个类
w1
signals:
void w1_signal_null();
void w1_signal_int(int a);
void w1_signal_int_int(int a,int b);
public slots:
void w1_slot_int(int a)
{
if(n1!=a)
{
n1=a;
}
}
void w1_slot_int_int(int a,int b)
{
if(n1!=a)
{
n1=a;
}
if(n2!=b)
{
n2=b;
}
}
w2
signals:
void w2_signal_null();
void w2_signal_int(int a);
void w2_signal_int_int(int a,int b);
public slots:
void w2_slot_int(int a)
{
qDebug()<<"rec:"<<a;
if(n1!=a)
{
n1=a;
}
}
void w2_slot_int_int(int a,int b)
{
qDebug()<<"rec:"<<a<<" "<<b;
if(n1!=a)
{
n1=a;
}
if(n2!=b)
{
n2=b;
}
}
w3
win2 *p_win2=new win2(this);
mainwin
win1 *w1 = new win1(this);
win3 *w3 = new win3(this);
初始化函数里面
connect(w1,SIGNAL(w1_signal_int(int)),(w3->p_win2),SLOT(w2_slot_int(int)));