发射信号和插槽 (Qt) 的信息和控制
Information and control on emitted signals and slots (Qt)
Qt是否提供功能来了解给定插槽待处理的排队信号的数量?有没有办法清除它们?例如,如果对连接到给定插槽的信号进行了多次发射,那么人们如何知道这些发射信号的数量?
QMetaObject::Connection 类有一个简洁的接口,似乎不提供相关的功能。删除接收信号的对象,从而破坏连接,可以解决问题。但是有没有办法在不断开插槽连接或删除接收对象的情况下做到这一点?
你问这个问题的原因很可能表明你的设计被破坏了。信号和插槽是一种解耦代码的机制。无论有多少发送者或接收者,连接在一起的对象都应该表现自己,当然不应该试图跟踪此类事件!
通过更改设计在源头解决问题会更明智。如果您因事件风暴而烦恼,例如由于更改插槽中小部件的数据,该插槽应该非常轻量级,并且仅通过调用update()
来安排小部件的更新,但绝不强制立即重新绘制。这利用了Qt完成的重绘事件压缩。您可能也希望压缩自己的事件。
Qt中的连接类型
Qt中的信号和插槽可以使用直接、排队或阻塞连接进行传递。自动类型并不是真正的固定连接类型。它是在每次信号发射时解析每个接收器的类型为直接或排队类型的指令。
直接连接就像任何间接函数调用一样:没有任何东西排队,插槽是从信号方法的主体中调用的:
// all direct-connected slots/functors are invoked before mySignal() returns
emit mySignal();
排队的连接将QMetaCallEvent
发布到接收对象线程的事件循环。该事件包含调用的参数,或携带函子。由QObject::event()
处理。您当然可以拦截此类事件。有关详细信息,请参阅此问题。
据我所知,无法访问队列。
首先,如果插槽位于 QWidget 子类中,在 GUI 线程中,那么您可以只更新成员变量并调用update()
,然后在调用时只使用 paintEvent()
中的当前值。这些是自动压缩的,因此无论调用多少次update()
都会只有一个重绘事件。
但是,如果插槽与绘画无关,或者根本不在 GUI 线程中,那么您需要其他东西。
对于许多需要这种情况的情况,一个简单的解决方案是使用第二个插槽和一个延迟为 0(如果需要,甚至更长的延迟)的单次 QTimer。
下面是一些示例代码,它应该让你明白我的意思:
// in constructor, set mActualSlotTimer to
// singleshot, interval 0, parent this (needed for multi-threaded use)
// and connect timeout() to privateActualSlot()
// public slot for receiving the signal from outside
void MyClass::actualSlot(int data) {
// class member to store the new data value until it can be set
mNewData = data;
// restart the timer, no matter if it was already running or not
mActualSlotTimer.start();
}
// "private" slot for actually doing the change
void MyClass::privateActualSlot() {
// maybe useful: if (this->mData == this->mNewData) return;
mData = mNewData;
// do whatever else needs to be done!
}
显然,如果您的公共插槽实际上没有任何参数,那么您不需要 mData
和 mNewData
.
关于这种方法需要注意的一件事是,它适用于所有连接,它不仅限于 Qt::QueuedConnecton
.因此,它也使使用Qt::BlockingQueuedConnection
变得毫无意义。
免责声明:我简要检查了Qt源代码,似乎使用间隔为0的计时器应该没问题:重新启动计时器将按预期工作。但是,如果似乎仍然有太多的调用要privateActualSlot
,那么提供一个合适的间隔可能是必要的。我通常想要一点延迟(例如 5 毫秒)来限制事情,而不是"尽可能频繁",所以没有用间隔 0 对此进行广泛测试。
- 正在查找文档以获得PS4平台的C++中的设备信息
- 为什么在运行时没有向我们提供有关分段错误的更多信息?
- 奇怪的(对我来说)返回声明 - 在谷歌上找不到任何关于它的信息
- 控制允许动态运行c++的并发操作数
- 从控制台中删除最后打印的元素
- 是否可以使用if constexpr删除控制流语句
- 如何设置一个范围来提取我想要获得的信息
- 无法在windows控制台中为C++程序提供必要的输入
- 系统参数信息A 与 SPI_GETMOUSE 返回 0
- 为什么 gcovr 会生成空覆盖率统计信息?
- 控制到达非空函数clang(-Wreturn-type)的末尾
- 查找 GCD:并非所有控制路径都返回值
- 我已经阅读了很多关于 2d 数组的信息,但我在作业中使用它时遇到了麻烦
- 通过 API 控制 DJI 相机
- 禁止在控制台上记录谷神星
- 是否可以使用一个类来控制 C++ 中另一个类的对象?(阿杜伊诺)
- 如何删除列出的"QGraphicsPathItem"对象以控制进程内存使用情况?
- Qt:显示聊天信息的最佳控制
- 如何解释显示在控制台上的c++错误信息
- 发射信号和插槽 (Qt) 的信息和控制