【QT信号和槽】学了C++不学QT就太亏了

⚠️作为一个学习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学习之旅,还希望您多多关注,多多三连支持!谢谢

评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值