这两个qt信号槽连接之间的功能区别是什么?



我正在使用Qt 5.9.2和Visual Studio 2015和QtDesigner来编程Windows GUI应用程序。我尝试通过以下调用连接我的一个操作:

connect(ui.myAction, &QAction::triggered, memberPtrToObjX_, &ClassX::Run);

但是,ClassX::Run 并不总是在单击菜单栏中的 myAction 后触发。在调查这个问题时,我认为,使用 lambda 语法的相同信号槽连接有效:

connect(ui.myAction, &QAction::triggered, [this](bool run) { memberPtrToObjX_->Run(run); });

我很确定,这两个调用在语法上都是正确的。此外,这两个调用都返回一个有效的 QMetaObject::Connection,如果我保存返回值并使用运算符 bool() 检查。

显然,我可以坚持使用有效的lambda版本,但是我很困惑,并且更愿意知道我的"解决方案"背后的原因。这两个调用之间是否有任何功能差异,从而解释了不同的行为?

QObject::connect()的两个调用(由 OP 公开)在调用connect()后修改this->memberPtrToObjX_的情况下行为不同。

第一个

connect(ui.myAction, &QAction::triggered, memberPtrToObjX_, &ClassX::Run);

调用
QMetaObject::Connection QObject::connect(
const QObject *sender, PointerToMemberFunction signal,
const QObject *receiver, PointerToMemberFunction method,
Qt::ConnectionType type = Qt::AutoConnection)
.

创建从发送方对象中的信号接收方对象中的方法的给定类型的连接。返回连接句柄,以后可用于断开连接。

因此,this->memberPtrToObjX_中的电流指针作为信号接收器连接。如果在connect()后修改this->memberPtrToObjX_,则对信号连接没有任何影响。

第二个

connect(ui.myAction, &QAction::triggered, [this](bool run) { memberPtrToObjX_->Run(run); });

调用
QMetaObject::Connection QObject::connect(
const QObject *sender, PointerToMemberFunction signal,
Functor functor)
.

创建从发送方对象中的信号函子的连接,并返回连接的句柄。

因此,(函子后面的)lambda作为接收器连接。lambda 在执行指针时(即触发信号时)以this->memberPtrToObjX_解析指针。


第二个区别(最初在 GM 的评论中发现)是连接类型:

第一个版本使用默认值Qt::AutoConnection(因为它没有显式定义)。带有 lambda 的版本始终使用Qt::DirectConnection代替。

如果this->memberPtrToObjX_中的点不"活"在同一线程中,则会出现差异。在这种情况下,Qt::AutoConnection解析为Qt::QueuedConnection而不是Qt::DirectConnection

我假设this->memberPtrToObjX_中的点会"生活"在同一QThread.如果没有,第二个版本(带有lambda)变得非常值得怀疑,因为它在不同的线程中调用对象的a成员函数"生活"(此时很难说出该线程在做什么)。这似乎效果更好,但很可能是"定时炸弹"。

最新更新