第65课 深入浅出信号与槽

1、 Qt中信号(SIGNAL)的本质

            

    1.1、 信号只是一个特殊的成员函数声明 
        1.1.1、 函数的返回值是void类型
        1.1.2、 函数只能声明不能定义(实际上定义的部分是由moc自动生成的)

    1.2、 信号必须使用signals关键字进行声明
        1.2.1、 函数的访问属性自动被设置为protected(即#define signals public)
        1.2.2、 只能通过emit关键字调用函数(发射信号

2、 信号与槽的对应关系

        


    2.1、信号与槽的对应关系
        2.1.1、 一个信号可以连接到多个槽(一对多,如signal5对应slot2、slot3)
        2.1.2、 多个信号可以连接到一个槽函数(多对一,如signal1、signal3对应slot1)
        2.1.3、 一个信号可以连接到另一个信号(转嫁,如signal4触发signal6,slot4接收)
        2.1.4、 连接可以被disconnect函数删除(移除,但一般不需要调用该函数,因为当一个对象被删除时,会自动断开与连接的信号或槽)

自定义槽函数

#ifndef _RXCLASS_H_
#define _RXCLASS_H_
#include <QObject>
#include <QDebug>
class RxClass : public QObject
{
    Q_OBJECT
public:
protected slots:
    void mySlot(int v)      //自定义接受处理槽
    {
        qDebug() << "void mySlot(int v)";
        //sender()为QObject类的protected成员函数
        qDebug() << "Sender" << sender()->objectName();
        qDebug() << "Receiver" << this->objectName();//接收处理对象name
        qDebug() << "Value" << v;
        qDebug() << endl;
    }
};
#endif // RXCLASS_H


自定义信号

#ifndef _TESTSIGNAL_H_
#define _TESTSIGNAL_H_
#include <QObject>
class TestSignal : public QObject
{
    Q_OBJECT        //继承自QObject,使用信号槽机制,必须使用该宏。
public:
    void send(int i)
    {
        emit testSignal(i);//发射信号
    }
signals://默认protected的。
    void testSignal(int v);
};
#endif // TESTSIGNAL_H


main.cpp

#include <QtCore/QCoreApplication>
#include <QDebug>
#include "TestSignal.h"
#include "RxClass.h"
void emit_signal()//发送信号到槽
{
    qDebug() << "emit_signal()" << endl;
    TestSignal t;
    RxClass r;
    t.setObjectName("t");
    r.setObjectName("r");
    QObject::connect(&t, SIGNAL(testSignal(int)), &r, SLOT(mySlot(int)));
    for(int i=0; i<3; i++)
    {
        t.send(i);
    }
}
//一信号对多槽
void one_to_multi()
{
    qDebug() << "one_to_multi()" << endl;
    TestSignal t;
    RxClass r1;
    RxClass r2;
    t.setObjectName("t");
    r1.setObjectName("r1");
    r2.setObjectName("r2");
    QObject::connect(&t, SIGNAL(testSignal(int)), &r1, SLOT(mySlot(int)));
    QObject::connect(&t, SIGNAL(testSignal(int)), &r2, SLOT(mySlot(int)));
    t.send(100);//发送一次相同的函数,两个接受者。
}
//多信号对一槽
void multi_to_one() //
{
    qDebug() << "multi_to_one() " << endl;
    TestSignal t1;
    TestSignal t2;
    RxClass r;
    t1.setObjectName("t1");
    t2.setObjectName("t2");
    r.setObjectName("r");
    QObject::connect(&t1, SIGNAL(testSignal(int)), &r, SLOT(mySlot(int)));
    QObject::connect(&t2, SIGNAL(testSignal(int)), &r, SLOT(mySlot(int)));
    t1.send(101);   //两个发送的信号被同一个槽接收。
    t2.send(102);
}
//(转嫁:一个信号触发另一个信号)
void signal_signal()
{
    qDebug() << "signal_signal() " << endl;
    TestSignal t1;
    TestSignal t2;
    RxClass r;
    t1.setObjectName("t1");
    t2.setObjectName("t2");
    r.setObjectName("r");
    QObject::connect(&t1, SIGNAL(testSignal(int)), &t2, SIGNAL(testSignal(int)));
    QObject::connect(&t2, SIGNAL(testSignal(int)), &r, SLOT(mySlot(int)));
    t1.send(101);   //有个间接多信号对一个槽的关系。
    t2.send(102);
}
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    //emit_signal();
    //one_to_multi();
    //multi_to_one();
    signal_signal();
    
    return a.exec();
}



3、  不可忽视的军规

    3.1、 Qt类只能在头文件中声明,不能放到cpp文件去声明
    3.2、 信号与槽的原型应该完全相同
    3.3、 信号参数多个槽参数时,多余的参数被忽略
    3.4、 槽函数的返回值必须是void类型
    3.5、 槽函数可以像普通成员函数一样被调用
    3.6、 信号与槽的访问属性(譬如private,public)对于connect/disconnect无效

4、  信号与槽的意义

    4.1、 最大限度的弱化了类之间的耦合关系
    4.2、 在设计阶段,可以减少不必要的接口类(抽象类)
    4.3、 在开发阶段,对象间的交互通过信号与动态绑定

5、小结

    5.1、 信号只是一个特殊的成员函数声明
    5.2、 信号必须使用signals关键字进行声明
    5.3、 信号与槽可以存在多种对应关系
    5.4、 信号与槽机制使得类间关系松散,提高类的可复用性 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值