Qt事件

作者: 仙人掌__ | 来源:发表于2024-02-25 09:30 被阅读0次

一、事件类型

1、事件分类

Qt中事件根据源头分为三种类型:

  • 自发事件:由操作系统产生(例如用户按下鼠标,操作系统会产生一个鼠标事件)然后提交到Qt的event loop

  • Post事件:由应用程序通过postEvent()提交给Qt的event loop的事件

  • Send事件: 由应用程序通过sendEvent()触发的事件,与Post不一样的是他不会提交到Qt的event loop中,是同步执行的。

2、event loop

当在main()函数中调用QApplication::exec()时会自动开启一个event loop循环,每一次循环都会按照如下的顺序处理事件

while (!exit_was_called) {
    while (!posted_event_queue_is_empty) {
        process_next_posted_event();
    }
    while (!spontaneous_event_queue_is_empty) {
        process_next_spontaneous_event();
    }
    while (!posted_event_queue_is_empty) {
        process_next_posted_event();
    }
}

3、postEvent()和sendEvent()

大部分情况下的事件(例如鼠标事件、绘制事件,尺寸调整事件)都是由Qt自动帮我们提交到event loop,然后传递给对应的接受者,我们只需要实现对应的事件hander即可。例如QWidget中对应的各种各样的hander

class MyButton : public QPushButton{
public:
    MyButton(QWidget *parent = nullptr) : QPushButton(parent)
    {
        setStyleSheet("background-color: #ffffff;");
    }

    void mousePressEvent(QMouseEvent *e) override {
        qDebug() << "MyButton::mousePressEvent()";
        QPushButton::mousePressEvent(e);
        e->ignore();
    }

    void keyPressEvent(QKeyEvent *) override
    {
        qDebug() << "MyButton::keyPressEvent()";
    }

    bool event(QEvent *event) override
    {
        if (event->type() == QEvent::MouseButtonPress) {
            qDebug() << "MyButton::event()";
        }
        return QPushButton::event(event);
    }
};

其中event(QEvent *event)的默认实现流程大概如下:

1、根据event->type()的事件类型调用对应的xxxEvent()函数,大部分的系统事件都有对应的hander

2、没有对应xxxEvent()函数的事件则采用默认实现

可以通过QApplication::postEvent()或者QApplication::sendEvent()手动发送一个事件,前者将事件提交到event loop,后者直接触发

// mouseEvent事件必须分配在堆上,内部会持有它,当事件在event loop被使用后,会被自动delete。
auto *mouseEvent = new QMouseEvent(QEvent::MouseButtonPress, QPoint(50, 50), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
QApplication::postEvent(myButton, mouseEvent);
// mouseEvent事件会被myButton立即处理,且内部不持有它,所以需要自己delete;或者将mouseEvent分配在栈上
auto *mouseEvent = new QMouseEvent(QEvent::MouseButtonPress, QPoint(50, 50), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
QApplication::sendEvent(myButton, mouseEvent);
delete mouseEvent;

二、事件派发

事件响应链

窗口-->父视图-->子视图1-->子视图2....-->子视图n;越在顶端的子视图则优先处理事件

image.png

用户在按钮上点击一下,操作系统会生成一个QMouseEvent事件,添加到Qt的 Event loop,Qt首先找到最终能够响应该鼠标事件的子视图(鼠标点击的位置刚好在子视图上,且该子视图为可见的,处于隐藏状态或者被其它子视图覆盖都算不可见),最后在调用该子视图的event()函数,如果event()返回false,那么事件将传递给事件响应链的上一个视图,否则事件传递终止

三、事件过滤器

正常情况下,发送给一个QObject对象的事件首先会调用event()函数来进行处理,如果想抢在event()函数之前处该事件,可以给该对象添加一个事件过滤器对象,使用方法如下:

class EventFilter:public QObject
{
public:
    bool eventFilter(QObject *watched, QEvent *event) override
    {
        if (event->type() == QEvent::MouseButtonPress) {
            qDebug() << "EventFilter::eventFilter()";
            // 截获鼠标按下事件
            return true;
        }
        else if event->type() == QEvent::KeyPress{
            // 不处理键盘事件
            return false;
        }
        return QObject::eventFilter(watched, event);
    }
}

// 给myWidget对象添加事件过滤器
auto *myWidget = new MyWidget;
myWidget->installEventFilter(new EventFilter);

eventFilter()返回true代表事件直接被截获了,false则代表事件会丢回给原先对象的event()函数中去处理

四、消费事件

在事件传递的过程中,除了通过事件过滤器(即eventFilter())决定事件是否消费外,还可以通过调用event的accept()函数来消耗这个事件,当事件被消耗后,它将不再继续传递。

相关文章

  • 一个 Qt 事件对象的旅行

    Qt 的事件来自操作系统,Qt自己产生。当Qt应用程序运行时,qt有一个未处理的事件队列,每个事件处理周期内,将处...

  • Qt中事件的理解(1)

    1、Qt中的事件 Qt中,事件作为一个对象,继承自QEvent类,常见的有键盘事件QKeyEvent、鼠标事件QM...

  • Qt学习-(虚函数,界面原理等)

    Qt学习 事件:事件在Qt分很多种,例如鼠标,键盘,定时器,窗体大小,任何动作在GUI都可以触发某种事件, 根据C...

  • Qt开发系列3——Qt中的核心技术1

    简介 这里简单介绍Qt的一些核心机制,具体参见Qt文档。 主要包含内容: Qt的信号和槽,以及事件机制 Qt Ob...

  • 2020-11-20 Qt事件循环

    一 Qt事件循环:从队列中不断取出消息、处理消息的过程。 Qt会接管windows的原生窗口消息,翻译成Qt消息,...

  • QT事件循环

    Qt 事件和信号的关系 Qt的事件是windows的底层消息封装而成的。这个消息和MFC里的消息是同一概念,都是指...

  • Qt 键盘事件

    添加头文件 #include 重写函数 void keyPressEvent(QKeyEvent *); widg...

  • Qt 事件管理

    参考:Events and signals in PyQt5 所有的应用都是事件驱动的。事件大部分都是由用户的行为...

  • QT-事件

    事件 事件(event)是由系统或者 Qt 本身在不同的时刻发出的。 一些事件在对用户操作做出响应时发出,如键盘事...

  • mac下QWebEngineView禁用手势放大和下拉效果

    QWebEngineView手势放大原因 Qt具备手势相关的类和信号的,是支持mac原声手势的。 Qt的事件处理 ...

网友评论

      本文标题:Qt事件

      本文链接:https://www.haomeiwen.com/subject/zwqgadtx.html