我正在使用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成员函数"生活"(此时很难说出该线程在做什么)。这似乎效果更好,但很可能是"定时炸弹"。