在 Qt 中,connect 函数提供了多种不同的连接方式:
- 直接连接(Direct Connection):信号被发射时,槽函数立即执行,此时阻塞线程。直接连接默认使用 Qt::AutoConnection 模式。
QObject::connect(sender, SIGNAL(mySignal()), receiver, SLOT(mySlot()));
- 自动连接(Auto Connection):如果信号与槽都是在同一线程中,则使用直接连接;否则使用队列连接。
QObject::connect(sender, SIGNAL(mySignal()), receiver, SLOT(mySlot()), Qt::AutoConnection);
- 队列连接(Queued Connection):信号发射后,槽函数会被放入接收者所在线程的事件队列中,等待接收者线程轮询处理,此时不会阻塞线程。
QObject::connect(sender, SIGNAL(mySignal()), receiver, SLOT(mySlot()), Qt::QueuedConnection);
- 保留连接(BlockingQueued Connection):信号发射后,槽函数会被放入接收者所在线程的事件队列中,等待接收者线程轮询处理,并且当前线程会阻塞,直到槽函数执行完成。
QObject::connect(sender, SIGNAL(mySignal()), receiver, SLOT(mySlot()), Qt::BlockingQueuedConnection);
- 多线程连接(Direct Connection with Namespace):用于跨线程的信号和槽连接,需要在信号和槽名称前加上命名空间。
QObject::connect(sender, &Sender::mySignal, receiver, &Receiver::mySlot);
下面是一个示例,可以演示以上几种连接方式的使用:
#include <QCoreApplication>
#include <QDebug>
#include <QThread>
class Sender : public QObject
{
Q_OBJECT
public:
explicit Sender(QObject *parent = nullptr) : QObject(parent) {}
signals:
void mySignal();
public slots:
void send()
{
qDebug() << "Sender: emit mySignal";
emit mySignal();
}
};
class Receiver : public QObject
{
Q_OBJECT
public:
explicit Receiver(QObject *parent = nullptr) : QObject(parent) {}
public slots:
void mySlot()
{
qDebug() << "Receiver: mySlot called in thread" << QThread::currentThreadId();
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Sender sender;
Receiver receiver;
// 直接连接
QObject::connect(&sender, SIGNAL(mySignal()), &receiver, SLOT(mySlot()));
// 自动连接
QObject::connect(&sender, SIGNAL(mySignal()), &receiver, SLOT(mySlot()), Qt::AutoConnection);
// 队列连接
QObject::connect(&sender, SIGNAL(mySignal()), &receiver, SLOT(mySlot()), Qt::QueuedConnection);
// 保留连接
QObject::connect(&sender, SIGNAL(mySignal()), &receiver, SLOT(mySlot()), Qt::BlockingQueuedConnection);
// 多线程连接
QObject::connect(&sender, &Sender::mySignal, &receiver, &Receiver::mySlot);
QThread thread;
receiver.moveToThread(&thread);
thread.start();
sender.send();
thread.quit();
thread.wait();
return a.exec();
}
运行结果:
Sender: emit mySignal
Receiver: mySlot called in thread 0x700009c96000
Receiver: mySlot called in thread 0x700009cc9000
Receiver: mySlot called in thread 0x700009c96000
Receiver: mySlot called in thread 0x700009cc9000