c++ - Qt 中的事件队列

标签 c++ qt events

Qt 应用程序中有多少个事件队列?单击等事件在队列中排队。您还可以使用 postEvent 等函数查询事件。所有这些事件都在同一个队列中吗?如果是,有没有办法定义不同的队列?

最佳答案

通常,每个线程最多有一个事件队列。

可以有额外的事件队列,有两种不同的实现策略,取决于您是否保持与 ​​QCoreApplication::postEvent 的兼容性。

如果您不关心 QCoreApplication::postEvent 使用您的队列,一切都由您决定。您可以按照您希望的任何方式实现队列。请注意,Qt 没有实现将 QObject 标记为属于特定事件队列的方法。当您准备好从队列中传送事件时,您只需调用 QCoreApplication::notify,将目标对象指针和事件指针传递给它。十分简单。当然,您无法控制从默认队列传送到任何和所有对象的事件。

另一种方法是与QCoreApplication::postEvent 保持兼容。即,您以某种方式“标记”一个对象,使其事件由您的队列处理。您拦截即将传递给目标的事件,将其入队,并根据需要自行处理。

这是类似于 QStateMachine 的 hack。这很好。而且不好。以及介于两者之间的事情。值得了解它是如何完成的以及为什么。

分层状态机通常需要控制事件的传递并将它们自己的事件注入(inject)到队列中,排在其他事件之前。这是为了使状态转换事件以与导致转换的事件相关的正确顺序传递;此外,有时可能需要多次传递引起转换的事件,保留以供以后传递等。

这一切都面临着默认事件调度系统强制执行的严格事件生命周期。为了解决这个问题,QStateMachine 实现了它自己的事件队列。每当您对将传递给某个对象的事件声明转换时,状态机都会将自身安装为该对象的事件过滤器。

然后,只要原始事件到达目标对象,过滤器就会拦截该事件并阻止其传递到目标对象。现在它必须复制事件,并将其插入到自己的队列中。必须进行复制,因为一旦控件离开事件过滤器和/或目标对象的 event() 方法,事件将被事件调度程序删除。

不幸的是,在 Qt 6 之前,QEvent 是不可克隆的——至少不是公开的。有一些 clone functionality hidden in Qt's innards, usable by user code ,但它是一个私有(private) API,而不是基于虚拟复制构造函数惯用语。

Qt 6 添加了 QEvent::clone 方法,事件应该被假定为可克隆的。未移植到 Qt 6 的遗留代码中的自定义事件不支持此功能,如果它们携带数据,它们的克隆将无法完全发挥作用。

使用基于过滤器的习惯用法/hack,您可以实现属于某个事件队列的 QObject 的概念。当您的队列过滤目标对象上的事件、克隆它们并将它们排入队列以进行单独传送时,该对象在功能上驻留在您的事件队列中。当没有发生这样的过滤时,对象驻留在默认的每线程队列中。您也可以只拦截您的队列感兴趣的类型的事件,就像 QStateMachine 所做的那样。

关于c++ - Qt 中的事件队列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32172059/

相关文章:

c++ - 不同 vector 类型的列表?

java - 为什么(我的)Java 比 C++ 快 25 倍?

c++ - HTTP POST 中缺少内容类型。 QT使用Webview

c++ - 从qt进度条中删除文本

java - 当窗口失去焦点时隐藏 JDialog 窗口

c++ - 头文件中的 constexpr const char*

c++ - 具有原始数据指针和 emscripten 的对象

c++ - 错误看起来如此 main.cpp :(. text.startup+0xd6) : undefined reference to `vtable for Counter' ?

javascript - 单击元素时内部的元素检测

c# - 为什么 C# EventHandler 等于 MSN 示例中的事件?