# flechazo 的小知乎,欢迎大家造访啦😘

当使用 Qt 进行应用程序开发时,QObject::connect 是一个非常重要的函数,它被用于将信号与槽函数连接起来,实现对象之间的通信。通过这种机制,可以实现模块之间的解耦和灵活的交互。本文将详细介绍 QObject::connect 的用法。

# 1. QObject::connect 函数的基本语法

QObject::connect 的基本语法如下:

bool QObject::connect(const QObject *sender, const char *signal,
                      const QObject *receiver, const char *method,
                      Qt::ConnectionType type = Qt::AutoConnection);

其中各参数的含义如下:

  • sender :发出信号的对象。
  • signal :信号的名称。
  • receiver :接收信号的对象。
  • method :槽函数的名称。
  • type :连接类型,默认为 Qt::AutoConnection。

# 2. 信号与槽函数的声明

在使用 QObject::connect 进行连接之前,需要确保信号和槽函数在相应的类中进行了正确的声明。信号和槽函数的声明遵循特定的规则:

  • 信号的声明:在信号所属的类中使用 signals 关键字进行声明,通常在类的头文件中。例如:

    signals:
        void mySignal();
    
  • 槽函数的声明:在槽函数所属的类中进行声明,通常在类的头文件中,并且需要使用 slots 关键字进行修饰。例如:

    public slots:
        void mySlot();
    

# 3. 连接信号与槽函数

连接信号与槽函数是通过 QObject::connect 函数来实现的。该函数会根据参数指定的发送者、接收者、信号和槽函数进行连接。例如,以下代码将一个对象的信号连接到另一个对象的槽函数:

QObject::connect(senderObj, SIGNAL(mySignal()), receiverObj, SLOT(mySlot()));

在上述代码中,senderObj 是发出信号的对象,mySignal 是该对象的信号,receiverObj 是接收信号的对象,mySlot 是该对象的槽函数。当 senderObj 发出 mySignal 信号时,receiverObj 将自动执行 mySlot 槽函数的逻辑。

# 4. 信号与槽函数参数的匹配

在进行信号与槽函数的连接时,需要确保它们的参数类型和个数是匹配的。如果不匹配,编译器会发出警告,但并不会导致程序崩溃或出错。因此,在进行连接时,务必要确保信号与槽函数的参数类型和个数匹配,以避免意外错误的发生。

# 5. 连接类型

QObject::connect 函数还支持不同的连接类型,可以通过第五个参数 type 来指定。常用的连接类型有:

  • Qt::AutoConnection (默认):自动选择连接类型,如果发送者和接收者在同一线程,则使用 Qt::DirectConnection ,否则使用 Qt::QueuedConnection
  • Qt::DirectConnection :直接连接,信号发出时会立即调用槽函数,无论发送者和接收者是否在同一线程。
  • Qt::QueuedConnection :队列连接,信号发出时将事件放入接收者所在线程的事件队列中,在接收者线程的事件循环处理完当前事件后再调用槽函数。
  • Qt::BlockingQueuedConnection :阻塞队列连接,与 Qt::QueuedConnection 类似,但是信号发出者会等待槽函数执行完毕之后才继续执行。

# 6. 多线程连接

QObject::connect 函数还可以用于多线程连接。使用不同的连接类型可以实现跨线程的信号与槽函数通信。当发送者和接收者位于不同的线程时,一般使用 Qt::QueuedConnection 连接类型。具体的使用方法和注意事项,请参考 Qt 文档中关于多线程编程的部分。

以上就是 QObject::connect 函数的基本用法介绍。通过合理地使用信号与槽机制,可以实现模块之间的松耦合和高度可维护的代码结构。在实际开发中,建议详细阅读 Qt 文档,并根据具体的需求选择合适的连接类型和参数。

# 示例

image-20240128210411902

main.cpp

#include <QCoreApplication>
#include "Demo1.h"
#include "ReceClass.h"
#include <QDebug>

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

    //init
    ReceClass receClass;
    Demo1 demo1;
    Demo1 demo2;

    //bind
    qDebug() << QObject::connect(&demo1, &Demo1::sendMsg, &receClass, &ReceClass::receMsg, static_cast<Qt::ConnectionType>(Qt::QueuedConnection | Qt::UniqueConnection));
    qDebug() << QObject::connect(&demo2, &Demo1::sendMsg, &receClass, &ReceClass::receMsg, static_cast<Qt::ConnectionType>(Qt::QueuedConnection | Qt::UniqueConnection));

    //run
    demo1.setMsg("我爱你!");
    demo2.setMsg("滚!");

    demo1.start();
    demo2.start();

    return a.exec();
}

Demo1.cpp

#include "Demo1.h"
#include <QDebug>


void Demo1::run()
{
    for(int i = 0; i < 2; i++){

        emit sendMsg(this->m_msg);
        qDebug() << "emit " << this->m_msg << " over";
    }
    qDebug() << "msg:" << this->m_msg << " over";
}

void Demo1::setMsg(const QString &msg)
{
    this->m_msg = msg;
}

Demo1.h

#ifndef DEMO1_H
#define DEMO1_H

#include <QThread>

class Demo1 : public QThread
{
    Q_OBJECT
    void run() override;

public:
    void setMsg(const QString &msg);

signals:
    void sendMsg(QString msg);

private:
    QString m_msg;
};

#endif // DEMO1_H

ReceClass.cpp

#include "ReceClass.h"
#include <QDebug>
#include <QThread>

ReceClass::ReceClass(QObject *parent) : QObject(parent)
{

}

void ReceClass::receMsg(QString msg)
{
    qDebug() << "Get msg: " +  msg;
    QThread::sleep(1);
}

ReceClass.h

#ifndef RECECLASS_H
#define RECECLASS_H

#include <QObject>

class ReceClass : public QObject
{
    Q_OBJECT
public:
    explicit ReceClass(QObject *parent = nullptr);

public slots:
    void receMsg(QString msg);
};

#endif // RECECLASS_H
更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

flechazo 微信支付

微信支付

flechazo 支付宝

支付宝

flechazo 贝宝

贝宝