这两种qt信号槽连接有什么功能区别?

问题描述 投票:0回答:1

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

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

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

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

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

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

qt lambda signals-slots
1个回答
0
投票

在调用

QObject::connect()
之后修改
this->memberPtrToObjX_
时,
connect()
(由 OP 公开)的两个调用的行为不同。

第一个

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)
.

创建从 sender 对象中的 signalreceiver 对象中的 method 的给定类型连接。返回连接的句柄,稍后可用于断开连接。

因此,

this->memberPtrToObjX_
中的当前指针被连接为信号接收器。如果在
this->memberPtrToObjX_
之后修改
connect()
,这不会对信号连接产生任何影响。

第二个

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

来电

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

创建从 sender 对象中的 signalfunctor 的连接,并返回该连接的句柄。

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

this->memberPtrToObjX_
中的指针。


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

第一个版本使用默认值

Qt::AutoConnection
(因为它没有明确定义)。带有 lambda 的版本始终使用
Qt::DirectConnection
来代替。

如果

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

我假设

this->memberPtrToObjX_
中的受指点会“生活”在同一个
QThread
中。如果不是,第二个版本(使用 lambda)就会变得非常有问题,因为它调用对象的成员函数“生活”在不同的线程中(很难判断该线程此时正在做什么)。这只是似乎效果更好,但很可能是一个“定时炸弹”。

© www.soinside.com 2019 - 2024. All rights reserved.