# flechazo 的小知乎,欢迎大家造访啦😘
https://www.zhihu.com/people/jiu_sheng
当使用 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 文档,并根据具体的需求选择合适的连接类型和参数。
# 示例
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