⚠️作为一个学习C++的人,Qt的存在就意味着我们不能不学它!!!联合C++与Qt,你将有不一样的收获!
文章目录
一:信号和槽机制
信号槽是 Qt 框架引以为豪的机制之一。所谓信号槽,实际就是观察者模式。。当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal)这种发出是没有目的的,类似广播。如果有对象对这个信号感兴趣,它就会使用连接(connect)函数,意思是,将想要处理的信号和自己的一个函数(称为槽(slot))绑定来处理这个信号。也就是说,当信号发出时,被连接的槽函数会自动被回调。这就类似观察者模式:当发生了感兴趣的事件,某一个操作就会被自动触发。
1.1:信号和槽
connect()函数最常用的一般形式:connect(sender, signal, receiver, slot);
- sender:发出信号的对象
- signal:发送对象发出的信号
- receiver:接收信号的对象
- slot:接收对象在接收到信号之后所需要调用的函数
注意点:信号槽要求信号和槽的参数一致,所谓一致,是参数类型一致。如果不一致,允许的情况是,槽函数的参数可以比信号的少,即便如此,槽函数存在的那些参数的顺序也必须和信号的前面几个一致起来。这是因为,你可以在槽函数中选择忽略信号传来的数据(也就是槽函数的参数比信号的少),但是不能说信号根本没有这个数据,你就要在槽函数中使用(就是槽函数的参数比信号的多,这是不允许的)。
1.2:自定义信号和槽
使用connect()可以让我们连接系统提供的信号和槽。但是,Qt 的信号槽机制并不仅仅是使用系统提供的那部分,还会允许我们自己设计自己的信号和槽。
功能描述:自定义Teacher类 Student类
🍊下课后,老师会触发一个信号 饿了,学生响应该信号,请客吃饭
1.2.1:student.h
#ifndef STUDENT_H
#define STUDENT_H
#include <QObject>
class Student : public QObject
{
Q_OBJECT
public:
explicit Student(QObject *parent = nullptr);
signals:
public slots:
//早期QT版本必须写到public slots,高级版本可以写到public或者全局下
//返回值void 需要声明,槽函数也需要实现
//可以有参数,可以发生重载
void treat();
void treat(QString foodName);
};
#endif // STUDENT_H
1.2.1:teacher.h
#ifndef TEACHER_H
#define TEACHER_H
#include <QObject>
class Teacher : public QObject
{
Q_OBJECT
public:
explicit Teacher(QObject *parent = nullptr);
signals:
//自定义信号 写到signals下
//返回值是void 只需要声明,不需要实现
//可以有参数的,可以重载
void hungry();
void hungry(QString foodname);
public slots:
};
#endif // TEACHER_H
1.2.3:widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include<teacher.h>
#include<student.h>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private:
Ui::Widget *ui;
Teacher * pxl;//声明老师类对象
Student * st;//声明学生类对象
void classIsOver();//下课函数
};
#endif // WIDGET_H
1.3:链接自定义信号和槽
🍎🍎🍎🍎🍎🍎🍎:当信号和槽函数存在重载的时候:
1️⃣链接无参的信号和槽
connect(pxl, &Teacher::hungry, st, &Student::treat);
2️⃣链接带参数的信号和槽
当发生重载的时候,要利用函数指针找到地址,注意作用域
void(Teacher :: *teacherSignal)(QString) = &Teacher::hungry;
void(Student::*studentSlot)(QString) = &Student::treat;
connect(pxl,teacherSignal,st,studentSlot);
自定义信号槽需要注意的事项:
1️⃣发送者和接收者都需要是QObject的子类(当然,槽函数是全局函数、Lambda 表达式等无需接收者的时候除外);
2️⃣使用 signals 标记信号函数,信号是一个函数声明,返回 void,不需要实现函数代码;
3️⃣槽函数是普通的成员函数,作为成员函数,会受到 public、private、protected 的影响;
4️⃣使用 emit 在恰当的位置发送信号;
5️⃣使用QObject::connect()函数连接信号和槽。
6️⃣任何成员函数、static 函数、全局函数和 Lambda 表达式都可以作为槽函数
二:lambda表达式
C++11中的Lambda表达式用于定义并创建匿名的函数对象,以简化编程工作。首先看一下Lambda表达式的基本构成:
函数对象参数mutable或exception ->返回值{函数体}
1️⃣:函数对象参数:
[],标识一个Lambda的开始,这部分必须存在,不能省略。函数对象参数是传递给编译器自动生成的函数对象类的构造函数的。函数对象参数只能使用那些到定义Lambda为止时Lambda所在作用范围内可见的局部变量(包括Lambda所在类的this)。
下面主要介绍一个常用的函数对象参数:
- =。函数体内可以使用Lambda所在作用范围内所有可见的局部变量(包括Lambda所在类的this),并且是值传递方式(相当于编译器自动为我们按值传递了所有局部变量)。
🍎示例1:()
//lanbda
[=](){
//btn->setText("aa");
}();
注意:后面的(),如果不加只是函数声明,加了才是调用。
🍎示例2:返回值
int ret = [=]()->int{
return 1000;
}();
->返回值类型,标识函数返回值的类型,当返回值为void,或者函数体中只有一处return的地方(此时编译器可以自动推断出返回值类型)时,这部分可以省略。
🍎示例3:mutable可修改标示符
mutable声明,这部分可以省略。按值传递函数对象参数时,加上mutable修饰符后,可以修改按值传递进来的拷贝(注意是能修改拷贝,而不是值本身)。若不写mutable就不可以修改
三:connect与lambda表达式联动
QPushButton btn3 = new QPushButton;
btn3->setText("关闭");
btn3->move(100,0);
btn3->setParent(this);
connect(btn3, &QPushButton::clicked, this, [=](){//z这里的第三个参数this都可以省略
//这里面相当于调他的成员函数
//槽函数里面多个操作
this->close();
emit pxl->hungry("宫爆鸡丁");
})
}
lanbda表达式里面可以有多个操作!
后面我会根据自己学习Qt的进度,继续分享我的Qt学习之旅,还希望您多多关注,多多三连支持!谢谢