第65课 - 深入浅出信号与槽

版权声明:课程笔记内容整理于狄泰软件 https://blog.csdn.net/qq_39654127/article/details/81839194

1、深入浅出信号与槽 

一个事实 

         在实际的项目开发中,大多数时候是直接将组件中预定

         义的信号连接到槽函数;信号发射时槽函数被调用。 

深度的思考 

                      信号是怎么来的?又是如何发射的? 

Qt中信号(SIGNAL)的本质 

     -信号只是一个特殊的成员函数声明 

             • 函数的返回值是void类型 

             • 函数只能声明不能定义 

     -信号必须使用signals关键字进行声明 

             • 函数的访问属性自动被设置为protected 

             • 只能通过emit关键字调用函数(发射信号) 

 

信号定义示例 

信号与槽的对应关系 

        -一个信号可以连接到多个槽(一对多

        -多个信号可以连接到一个槽(多对一) 

        -一个信号可以连接到另一个信号(转嫁) 

        -连接可以被disconnect函数删除(移除) 

2、编程实验 

信号与槽的对应关系    65-1.pro 

自定义信号所在类 TestSignal.h

#include <QObject>

class TestSignal : public QObject
{
    Q_OBJECT

public:
    void send(int i)
    {
        emit testSignal(i);
    }
    
signals:
    void testSignal(int v);
};

自定义槽函数所在类 RxClass.h

#include <QObject>
#include <QDebug>

class RxClass : public QObject
{
    Q_OBJECT

protected slots:
    void mySlot(int v)
    {
        qDebug() << "void mySlot(int v)";
        qDebug() << "Sender: " << sender()->objectName();
        qDebug() << "Receiver: " << this->objectName();
        qDebug() << "Value: " << v;
        qDebug() << endl;
    }
};

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_to_signal()
{
    qDebug() << "signal_to_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接收t1的信号,接着将t2发送信号到槽,值为101,发送者t2
    t2.send(102);//然后t2再发出自己的信号,值102
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // emit_signal(); 
    // one_to_multi();
    // multi_to_one();
    // signal_to_signal();
    
    return a.exec();
}

依次调用以上函数

不可忽视的军规 ( 最好 

        1. Qt类只能在头文件中声明 

        2. 信号与槽的原型应该完全相同 

        3. 信号参数多于槽参数时,多于的参数被忽略 

        4. 槽函数的返回值必须是void类型 

        5. 槽函数可以像普通成员函数一样被调用 

        6. 信号与槽的访问属性对于connect / disconnect无效 

 

信号与槽的意义 

       -最大限度的弱化了类之间的耦合关系 

       -在设计阶段,可以减少不必要的接口类(抽象类)

       -在开发阶段,对象间的交互通过信号与槽动态绑定 

 

3、小结 

信号只是一个特殊的成员函数声明 

信号必须使用signals关键字进行声明 

信号与槽的可以存在多种对应关系 

信号与槽机制使得类间关系松散,提高类的可复用性 

猜你喜欢

转载自blog.csdn.net/qq_39654127/article/details/81839194