自学内容网 自学内容网

Qt中的事件队列

本文内容由智谱清言产生。

------

Qt中的事件队列

在Qt框架中,事件队列是由QEventLoop类管理的,它是事件驱动编程模型的关键组成部分。Qt中的事件队列用于存储和管理所有的事件,这些事件包括用户输入(如鼠标点击、键盘按键)、窗口系统事件、定时器事件等。

以下是Qt中事件队列的基本概念和工作流程:

基本概念

  • QEvent:Qt中所有事件的基础类,它包含了事件类型、时间戳和其他与事件相关的信息。
  • QCoreApplication:Qt应用程序的核心类,它包含了一个事件循环,用于处理事件队列中的事件
  • QEventLoop:管理事件循环的类,可以用来处理事件队列中的事件
  • QObject:Qt中几乎所有的类都继承自QObject,它可以接收和处理事件

工作流程

  1. 事件产生:当用户与GUI交互或者应用程序内部发生某些操作时,事件被创建。
  2. 事件入队:创建的事件被放入事件队列中,等待被处理。
  3. 事件循环QCoreApplicationQApplication对象维护一个事件循环,该循环不断地从事件队列中取出事件。
  4. 事件分发:事件循环将事件分发给相应的QObject对象,通常是窗口部件(QWidgetQGraphicsItem)。
  5. 事件处理:目标对象根据事件的类型调用相应的事件处理函数(如mousePressEventkeyPressEvent等)。

示例

以下是一个简单的Qt事件队列处理的例子:

#include <QApplication>
#include <QWidget>
#include <QEvent>

class MyWidget : public QWidget {
public:
    MyWidget(QWidget *parent = nullptr) : QWidget(parent) {}

protected:
    void mousePressEvent(QMouseEvent *event) override {
        // 处理鼠标点击事件
        qDebug("Mouse Pressed!");
    }

    bool event(QEvent *event) override {
        // 可以在这里处理所有事件,或者调用基类的实现
        if (event->type() == QEvent::MouseButtonPress) {
            // 处理鼠标点击事件
            qDebug("Event: Mouse Pressed!");
            return true; // 表示事件已被处理
        }
        return QWidget::event(event); // 其他事件交由基类处理
    }
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    MyWidget widget;
    widget.show();
    return app.exec(); // 进入事件循环
}

在这个例子中,MyWidget类继承自QWidget,并重写了mousePressEventevent方法来处理鼠标点击事件。当用户点击窗口时,Qt会创建一个QMouseEvent对象并将其放入事件队列中。事件循环会取出这个事件,并将其分发给MyWidgetevent方法。

app.exec()是进入Qt事件循环的入口点,它将开始处理事件队列中的事件,直到应用程序退出。

为什么按照上面的写法,当连续点击时,仍会打印出"Mouse Pressed!"?

因为连续点击时

触发的是QEvent::MouseButtonDblClick

而不是QEvent::MouseButtonPress 

 [virtual] bool QObject::event(QEvent *e)

This virtual function receives events to an object and should return true if the event e was recognized and processed.

recognized:被识别

The event() function can be reimplemented to customize the behavior of an object.

customize:订制

Make sure you call the parent event class implementation for all the events you did not handle.

implementation:实施,执行

Example:

  class MyClass : public QWidget
  {
      Q_OBJECT

  public:
      MyClass(QWidget *parent = 0);
      ~MyClass();

      bool event(QEvent* ev)
      {
          if (ev->type() == QEvent::PolishRequest) {
              // overwrite handling of PolishRequest if any
              doThings();
              return true;
          } else  if (ev->type() == QEvent::Show) {
              // complement handling of Show if any
              doThings2();
              QWidget::event(ev);
              return true;
          }
          // Make sure the rest of events are handled
          return QWidget::event(ev);
      }
  };

该函数什么时候返回false?

当这个函数返回false时,意味着事件没有被处理。

以下是一些可能导致 QObject::event(QEvent *e) 返回 false 的情况:

  1. 未知事件类型:如果传入的事件类型是QObject不识别的,默认的实现将不会处理它,因此返回false

  2. 事件过滤:如果在事件到达QObject::event()之前,已经被一个事件过滤器(eventFilter)处理并吞没了(即事件过滤器返回true),那么QObject::event()将不会处理该事件,并返回false

  3. 重写且未处理:重写了QObject::event()方法后,如果你没有处理事件,并且也没有调用基类的实现,那么你需要告诉Qt事件系统这个事件没有被处理,通过返回false来实现。

  4. 故意忽略:在某些情况下,你可能故意不想处理某个事件,因此你的event()方法可以决定忽略该事件并返回false

在Qt中,你可以通过postEventsendEvent方法向任何QObject发送事件,这些事件将被添加到事件队列中,等待被处理。postEvent会将事件放入队列中,而sendEvent会立即分发事件,但不会立即处理。 

    QCoreApplication::postEvent(&widget, new QMouseEvent(QEvent::MouseButtonPress,  // 事件类型
                                                         QPointF(100, 100),         // 鼠标位置
                                                         Qt::LeftButton,            // 被按下的鼠标按钮
                                                         Qt::NoButton,              // 没有其他按钮被按下
                                                         Qt::NoModifier)); // 没有修饰键


原文地址:https://blog.csdn.net/weixin_51883798/article/details/143654197

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!