如图,首先 connect
是线程安全的。其次它有很多重载,当然最重要的还是QT4
连接和QT5
连接的区别,这个函数重载表示connect
函数也是支持lambda
函数的。
cpp
connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
connect 函数的第五个参数
了解 connect
的第五个参数是非常重要的。其中Qt::UniqueConnection
是比较特殊的,它仅仅用于connect
的在两个对象之间一个信号和一个槽之间连接的唯一性。注意 在QT中一个对象的信号重复连接到另外一个对象的槽上,那么当信号发送时,每个连接的槽都会执行。如果只希望连接一次那么就可以使用Qt::UniqueConnection
。当出现重复的连接时就会连接失败。问题 如何判断连接是否失败了?答案就是connect
的返回值。
因为QMetaObject::Connection
重载了运算符bool
所以可以将该类直接用于条件判断。代码如下
cpp
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
QMetaObject::Connection con = connect(ui->pushButton, &QPushButton::clicked, this, &Widget::slotClicked, Qt::UniqueConnection);
QMetaObject::Connection con_1 = connect(ui->pushButton, &QPushButton::clicked, this, &Widget::slotClicked, Qt::UniqueConnection);
if(con_1){
qDebug() << QStringLiteral("第二次连接成功");
}else{
qDebug() << QStringLiteral("第二次连接失败");
}
}
Widget::~Widget()
{
delete ui;
}
void Widget::slotClicked()
{
qDebug() << QStringLiteral("按钮被点击了");
}
这里又可以体现出lambda
表达式的坏处。lambda
最大的好处就是使用非常方便。不好的地方有使用lambda函数导致调试困难。
cpp
QMetaObject::Connection con = connect(ui->pushButton, &QPushButton::clicked, this, [](){
qDebug() << QStringLiteral("按钮被点击了");
}, Qt::UniqueConnection);
if(con){
qDebug() << QStringLiteral("con连接成功");
}else{
qDebug() << QStringLiteral("con连接失败");
}
QMetaObject::Connection con_1 = connect(ui->pushButton, &QPushButton::clicked, this, [](){
qDebug() << QStringLiteral("按钮被点击了");
}, Qt::UniqueConnection);
if(con_1){
qDebug() << QStringLiteral("con_1连接成功");
}else{
qDebug() << QStringLiteral("con_1连接失败");
}
此时就算两个匿名函数的函数体一样,但是由于名字不一样所以两个都可以连接成功。使用匿名函数导致调试困难
即使是debug模式仍然不会进入断点。
剩下的四个参数
Qt::AutoConnection
默认就是此链接,如果发送对象和接收对象在同一个线程,那么就是Qt::DirectConnection
链接如果不是在同一个线程上那么就是Qt::QueuedConnection
Qt::BlockingQueuedConnection
和Qt::QueuedConnection
相同,不同的是发送信号的线程将会阻塞直到被执行的槽函数返回。如果在同一个线程进行该参数的连接会导致死锁。