Qt中的事件队列

时间:2015-08-23 22:10:55

标签: c++ qt events

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

1 个答案:

答案 0 :(得分:2)

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

可以有其他事件队列,两种实现策略在是否与QCoreApplication::postEvent保持兼容方面有所不同。

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

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

这是QStateMachine - 就像黑客一样。这很好。而且很糟糕。介于两者之间。值得了解它是如何完成的以及为什么。

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

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

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

不幸的是,QEvent不可克隆 - 至少不是公开的。有一些clone functionality hidden in Qt's innards, usable by user code,但它是一个私有API,而不是基于虚拟拷贝构造函数的习惯用法。

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