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事件队列处理的例子:

cpp 复制代码
#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:

cpp 复制代码
  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会立即分发事件,但不会立即处理。

cpp 复制代码
    QCoreApplication::postEvent(&widget, new QMouseEvent(QEvent::MouseButtonPress,  // 事件类型
                                                         QPointF(100, 100),         // 鼠标位置
                                                         Qt::LeftButton,            // 被按下的鼠标按钮
                                                         Qt::NoButton,              // 没有其他按钮被按下
                                                         Qt::NoModifier)); // 没有修饰键
相关推荐
qq_430583972 小时前
QT笔记- QTreeView + QFileSystemModel 当前位置的保存与恢复 #选中 #保存当前索引
开发语言·笔记·qt
小王爱吃月亮糖2 小时前
QT-QVariant类应用
开发语言·c++·笔记·qt·visual studio
阿松のblog3 小时前
pyQt5实现目标检测可视化001
开发语言·qt·目标检测
沐泽Mu12 小时前
嵌入式学习-QT-Day05
开发语言·c++·qt·学习
StringerChen13 小时前
Qt ui提升窗口的头文件找不到
开发语言·qt
沐泽Mu15 小时前
嵌入式学习-QT-Day07
c++·qt·学习·命令模式
沐泽Mu15 小时前
嵌入式学习-QT-Day09
开发语言·qt·学习
林浔090620 小时前
QT信号槽
开发语言·qt
kiiila21 小时前
【Qt】编辑框/按钮控件---实现HelloWorld
开发语言·qt
lw向北.1 天前
Qt For Android之环境搭建(Qt 5.12.11 Qt下载SDK的处理方案)
android·开发语言·qt