QCoreApplication各种Event处理函数异同

1.QT应用程序自身产生事件的2种方式

    程序产生事件有两种方式, 一种是调用QApplication::postEvent(), 例如QWidget::update()函数,当需要重新绘制屏幕时,程序调用update()函数,new出来一个paintEvent,调用 QApplication::postEvent(),将其放入Qt的消息队列中,等待依次被处理;另一种方式是调用sendEvent()函数,事件不会放入队列, 而是直接被派发和处理, QWidget::repaint()函数用的就是阻塞型的。

    sendEvent()中事件对象的生命期由Qt程序管理,支持分配在栈上和堆上的事件对象;postEvent()中事件对象的生命期由Qt平台管理,只支持分配在堆上的事件对象,事件被处理后由Qt平台销毁。

[static] bool QCoreApplication::sendEvent(QObject *receiver, QEvent *event)

阻塞型事件发送,事件发送后需要等待事件处理完成。

使用notify()函数将事件直接发送到接收者receiver。 返回从事件处理程序返回的值。发送事件后,不会删除该事件。 通常的方法是在堆栈上创建事件,例如:

QMouseEvent event(QEvent::MouseButtonPress, pos, 0, 0, 0);

QApplication::sendEvent(mainWindow, &event);

另请参见postEvent()和notify()。

[static] void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority = Qt::NormalEventPriority)

非阻塞型事件发送,事件发送后立即完成。

将事件event(对象接收者作为事件的接收者)添加到事件队列中并立即返回。该事件必须在堆上分配,因为发布事件队列将拥有该事件的所有权,并在发布后将其删除。 发布事件后,访问该事件并不安全。当控制权返回到主事件循环时,将使用notify()函数发送队列中存储的所有事件。事件按优先级从高到低的顺序排序,即优先级高的事件在优先级较低的事件之前排队。 优先级可以是任何整数值,即介于INT_MAX和INT_MIN之间(包括两端); 有关更多详细信息,请参见Qt :: EventPriority。 具有相同优先级的事件将按照发布的顺序进行处理。

注意:此函数是线程安全的。

另请参见sendEvent(),notify(),sendPostedEvents()和Qt :: EventPriority。

注意事项:

sendEvent()中事件对象的生命期由Qt程序管理,支持分配在栈上和堆上的事件对象;postEvent()中事件对象的生命期由Qt平台管理,只支持分配在堆上的事件对象,事件被处理后由Qt平台销毁。

sendEvent()立即同步处理要发送的event。当sendEvent()返回的时候, 表示相关的事件过滤器或目标对象处理完了event。对于多数的event类, 有一个成员函数 isAccepted() 可以用来判别event事件是已被接受处理或被拒绝处理。

postEvent()将event提交到一个事件队列中等待调度。在下一次 Qt 的主 event loop 运行的时候,主 event loop 就会调度所有提交到队列中的 event, 以某种优化的方式。例如,如果有几个 resize event,他们就会被压缩成一个事件。同样适用于 paint events: QWidget::update() 调用postEvent(), 以避免多次重画来避免闪烁以及提高速度。

postEvent()也被用于对象的初始化过程,因为提交过的 event 通常在相应对象初始化完毕后极短的时间内就会被调度在实现一个控件的时候,在自定义控件的 constructor 中尽早支持事件机制是非常重要的在可能接受到任何事件之前,确保尽早初始化成员变量

2.类似Flush的Posted排队事件处理调用

[static] void QCoreApplication::sendPostedEvents(QObject *receiver = nullptr, int event_type = 0)

立即分派所有先前在QCoreApplication :: postEvent()中排队的事件,这些事件是针对对象接收者的,事件类型为event_type。窗口系统的事件不是由此函数调度的,而是由processEvents()调度的。如果receiver为null,则将为所有对象发送event_type事件。 如果event_type为0,则将所有事件发送给接收者。

注意:必须从其QObject参数接收器所在的线程中调用此方法。

另请参见flush()和postEvent()。

3.所有未决事件处理调用

[static] void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents)

根据指定的标志处理调用线程的所有未决事件,直到没有更多事件可处理为止。当程序忙于执行长时间的操作(例如,复制文件)时,可以偶尔调用此函数。如果您正在运行连续调用此函数的本地循环,而没有事件循环,则不会处理DeferredDelete事件。 这可能会影响小部件的行为,例如 QToolTip,依赖DeferredDelete事件才能正常运行。 一种替代方法是从该本地循环中调用sendPostedEvents()。调用此函数仅处理调用线程的事件。

注意:此函数是线程安全的。

另请参见exec(),QTimer,QEventLoop :: processEvents(),flush()和sendPostedEvents()。

[static] void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags, int maxtime)

此函数使processEvents()重载。在最大时间(毫秒)内处理调用线程的待处理事件,直到没有更多事件可处理(以时间较短者为准)。您可以在程序忙于长时间执行操作(例如,复制文件)时偶尔调用此函数。调用此函数仅处理调用线程的事件。

注意:此函数是线程安全的。

另请参见exec(),QTimer和QEventLoop :: processEvents()。

4.发送事件到接收者

[virtual] bool QCoreApplication::notify(QObject *receiver, QEvent *event)

发送事件到接收者:接收者->事件(事件)。返回从接收者的事件处理程序返回的值。请注意,对于发送到任何线程中任何对象的所有事件,将调用此函数。

对于某些类型的事件(例如鼠标和按键事件),如果接收者对事件不感兴趣(例如,它返回false),则事件将传播到接收者的父对象,依此类推直至顶级对象。

事件有五种不同的处理方式:重新实现此虚拟功能只是其中之一。下面列出了所有五种方法:

重新实现paintEvent(),mousePressEvent()等。这是最常见,最简单且功能最弱的方法。

重新实现此功能。这非常强大,可以提供完全的控制;但一次只能激活一个子类。

在QCoreApplication :: instance()上安装事件过滤器。这样的事件过滤器能够处理所有小部件的所有事件,因此它与重新实现notify()一样强大。此外,可能有多个应用程序全局事件过滤器。全局事件过滤器甚至可以查看禁用小部件的鼠标事件。请注意,仅针对驻留在主线程中的对象调用应用程序事件过滤器。

重新实现QObject :: event()(与QWidget一样)。如果这样做,则可以按Tab键,然后可以在所有特定于窗口小部件的事件过滤器之前查看事件。

在对象上安装事件过滤器。这样的事件过滤器将获取所有事件,包括Tab和Shift + Tab键按下事件,只要它们不更改焦点窗口小部件即可。

未来发展方向:对于Qt 6中位于主线程之外的对象,将不会调用此函数。需要该功能的应用程序应同时为其事件检查需要找到其他解决方案。该更改可能会扩展到主线程,从而导致不建议使用此功能。
警告:如果重写此功能,则必须确保在处理应用程序对象开始之前,所有处理事件的线程都停止这样做。这包括您可能正在使用的其他库启动的线程,但不适用于Qt自己的线程。
另请参见QObject :: event()和installNativeEventFilter()。

5.自定义事件的处理

[virtual protected] void QObject::customEvent(QEvent *event)

可以在子类中重新实现此事件处理程序,以接收自定义事件。 自定义事件是用户定义的事件,其类型值至少等于QEvent :: Type枚举的QEvent :: User项,并且通常是QEvent子类。 该事件在event参数中传递。

子类自己实现的虚函数,当传入QEvent类型超出內建类型时,由event()调用。

另请参见event()和QEvent。

 

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值