Qt的信号与槽机制

  • Post author:
  • Post category:其他




什么是信号与槽机制

在C++中,对象与对象之间的通信是要通过调用成员函数的方式来实现的。Qt提供了一种在对象与对象之间的通信方式:信号与槽机制。

在Qt中,如果一个类希望使用信号与槽的功能,那么就必须在其中声明Q_OBJECT,这个宏提供了信号与槽机制、国际化、不基于C++ RTTI的反射能力。

class myconnect: public QWidget{
    Q_OBJECT // 声明Q_OBJECT
public:
    myconnect(QWidget *parent=nullptr);
    ~myconnect();
private:
    QPushButton button1;
};



信号与槽机制的原理

信号与槽机制的原理:当某个事件发生后,就广播一个信号,如果有对象对这个信号感兴趣,那么就可以使用connect函数,将此信号与自己的一个函数进行绑定。那么当这个信号被发出时,绑定的函数就会被调用。connect函数:

connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
                                     const typename QtPrivate::FunctionPointer<Func2>::Object *receiver, Func2 slot,
                                     Qt::ConnectionType type = Qt::AutoConnection)
  • sender: 发出信号的对象
  • signal:发出信号的对象发出的信号
  • receiver:接收信号的对象
  • slot:接收信号的对象在接收信号后执行的函数
myconnect::myconnect(QWidget *parent): QWidget(parent){
    button1.setParent(this);
    button1.setText("close");
    button1.move(100,100);
    connect(&button1,&QPushButton::pressed,this,&myconnect::close);

}



信号的绑定

  • 一个信号可以绑定多个槽函数:
connect(sender,SIGNAL(signal),receiverA,SLOT(slotA));
connect(sender,SIGNAL(signal),receiverB,SLOT(slotB));
connect(sender,SIGNAL(signal),receiverC,SLOT(slotC));
  • 多个信号绑定到同一个槽函数:
connect(senderA,SIGNAL(signalA),receiver,SLOT(slot));
connect(senderB,SIGNAL(signalB),receiver,SLOT(slot));
connect(senderC,SIGNAL(signalC),receiver,SLOT(slot));
  • 一个信号绑定到另一个信号:

    当sender发送信号给signalA时,receiver在接收到signalA信号时发出信号signalB。
connect(sender,SIGNAL(signalA),receiver,SIGNAL(signalB));
  • 将信号与槽函数解绑:
disconnect(sender,SIGNAL(signal),receiver,SLOT(slot));

信号与槽机制与真正的调用函数相比,时间的消耗是很大的,所以在嵌入式的开发中,极不推荐使用信号与槽机制开发。



自定义槽函数

它其实就是一个函数而已,所以只需要把它定义出来,然后把函数指针传给connect函数。

myconnect.h:

#include <QPushButton>
#include <QWidget>

class myconnect: public QWidget{
    Q_OBJECT
public:
    myconnect(QWidget *parent=nullptr);
    void mySlot();
    ~myconnect();
private:
    QPushButton button1;
};

myconnect.cpp:

#include "myconnect.h"

myconnect::myconnect(QWidget *parent): QWidget(parent){
    button1.setParent(this);
    button1.setText("close");
    button1.move(100,100);
    connect(&button1,&QPushButton::pressed,this,&myconnect::mySlot);

}

void myconnect::mySlot(){
    button1.setText("Open");
}

myconnect::~myconnect(){}



自定义信号

槽函数可以传递参数,我们通过自定义信号的例子一同来说明。

自定义信号是一个函数声明,返回类型是void,不需要任何实现。在声明处用signals标记信号。使用emit在适合地方发送信号。

自定义信号的特点:

  • 无须实现
  • 返回类型只能是void
  • 可以有参数

myconnect.h:

class myconnect: public QWidget{
    Q_OBJECT
public:
    myconnect(QWidget *parent=nullptr);
    void mySlot(QString message); // 自定义带参数的槽函数
    ~myconnect();
signals:
    void mySignal(QString message); // 自定义信号
private:
    QPushButton button1;
};

myconnect.cpp:

connect(this,&myconnect::mySignal,this,&myconnect::mySlot);
QString message = "Hello Qt";
emit mySignal(message);

void myconnect::mySlot(QString message){
    button1.setText(message);
}

注意:信号函数的参数列表要与槽函数的一致。



槽函数类型

槽函数可以是任何成员函数、静态成员函数、全局函数、Lambda函数。

  • 任何成员函数: 如上述的例子
  • 全局函数
 void hello();
myconnect::myconnect(QWidget *parent): QWidget(parent){
    button1.setParent(this);
    button1.setText("close");
    button1.move(100,100);

    connect(&button1,&QPushButton::pressed,this,&hello);
}
 void hello(){
    qDebug() << "hello 8888";
}
  • 静态成员函数

    myconnect.h:
class myconnect: public QWidget{
    Q_OBJECT
public:
    myconnect(QWidget *parent=nullptr);
    static void staticHello();
    ~myconnect();
private:
    QPushButton button1;
};

myconnect.cpp

myconnect::myconnect(QWidget *parent): QWidget(parent){
    button1.setParent(this);
    button1.setText("close");
    button1.move(100,100);
connect(&button1,&QPushButton::pressed,this,&myconnect::staticHello);
}

void myconnect::staticHello(){
    qDebug() << "hello 8888000";
}



Lambda函数

myconnect::myconnect(QWidget *parent): QWidget(parent){
    button1.setParent(this);
    button1.setText("close");
    button1.move(100,100);

    connect(&button1,&QPushButton::pressed,this,[]{
        qDebug() << "9999999999";
    });
}

关于Lambda函数,我们将会在另一篇文章里详细分享。



版权声明:本文为weixin_40763897原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。