QT事件机制

事件就是从抽象QEvent类中派生的对象,表示发生在应用程序内部或由于应用程序需要了解的外部活动而发生的事情。例如当用户按下鼠标、敲下键盘就会产生QMouseEvent和QKeyEvent;系统自动发出的QTimerEvent事件等。Qt事件系统是依托于元对象系统的,所有的QObject类都可以接收/处理QEvent事件。

1,事件的产生

事件就是对象,派生自QEvent抽象类,事件的产生,就是创建一个对象。例如在一个窗口界面,当我们鼠标点击、双击、移动等,就会产生一个QMouseEvent事件对象。事件的来源一般分为三个,来自窗口系统,例如鼠标键盘产生的QMouseEvent和QKeyEvent;来自其他程序,比如 QTimerEvent;来自Qt程序本身,一些自定义的事件等。

2, 事件类和事件类型

Qt中所有事件类都是继承QEvent,用户输入类事件继承关系。事件类都有个唯一身份值:type 值,也就是事件类型。需要注意有些事件类可能对应于多个事件类型,例如QMouseEvent类对应于鼠标按压事件,鼠标双击事件,鼠标移动事件等。

 3,事件派发

当事件发生时Qt通过构造适当的QEvent子类的实例来表示一个事件,并通过调用其event()函数将其传递到 QObject的特定实例 (或其子类之一)。event()函数不处理事件本身,而是根据所传递事件的类型,调用对应的事件处理程序,并根据该事件被接受还是忽略,发送响应。许多应用程序都希望创建并发送自定义的事件,Qt提供了一些事件发送函数:

static bool QCoreApplication::sendEvent(QObject *receiver, QEvent *event);
static bool QCoreApplication::postEvent(QObject *receiver, QEvent *event);
static void QCoreApplication::sendPostedEvents(QObject *receiver, int event_type);

(1)sendEvent()直接将event事件发送给receiver接受者,立即处理事件。返回值是事件过滤器
和/或对象本身已经处理了该事件。对于许多事件类,有一个称为 isAccepted()的函数,该
函数告诉该事件是被最后一个调用的处理程序接受还是拒绝。
(2)postEvent()将接受者receiver和事件event发布到队列中,以供以后分派。下次Qt的主事件循环运行时,它将分派所有已发布的事件,并进行一些优化。例如,如果有多个调整大小事件,它们将被视为为一个。这同样适用于绘画事件中,如QWidget:: update()调用postEvent(),通过避免多次重新绘画来消除闪烁并提高速度。

(3)sendPostedEvents函数将事件队列中的接受者为receiver,事件类似为event_type的所有事件立即发送给 receiver进行处理。来自窗口系统的事件是由processEvent()进行处理。

void MainWindow::handletimeout()
{
     myevent *mypostEvent = new myevent();
     //使用postevent方式发送,事件添加到事件队列,此事件分配给this来处理,系统会自动释放的。
     QCoreApplication::postEvent(this, mypostEvent);
}

4,事件处理

一个类接收到应用程序派发来的事件后,调用其event()函数处理,该函数是QObject类中定义的一个虚函数。任何从QObject派生的类都可以重新实现该函数。在event()函数中我们可以设置是否接收事件,QEvent类中有accept()函数,表示接收事件并对事件进行处理,ignore()函数,表示不接收该事件。不接受的事件将会传播到接受者的父容器组件中,由父容器的event()函数去处理。QWidget类是所有窗口类的基类,它重新实现了event()函数,并对一些典型的事件定义了专门处理函数,event()函数会根据事件的类型自动去运行相应的事件处理函数,这些处理函数是pro-tected virtual, 不能被外部调用,但可以被派生类重新实现。每个事件都有关联的类型,在 QEvent::Type中定义了相关类型,并且可以用作运行时类型信息的便捷来源,以确定构造给定事件对象的子类。

void mousePressEvent(QMouseEvent *event); // 鼠标按下,对应事件类型
QEvent::MouseButtonPress
void mouseMoveEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
void mouseDoubleClickEvent(QMouseEvent *event);
void wheelEvent(QWheelEvent *event);
void keyPressEvent(QKeyEvent *event);
void closeEvent(QCloseEvent *event);
void resizeEvent(QResizeEvent *event);
void paintEvent(QPaintEvent *event);

5,事件过滤器

事件会被派发给接受者,接受者通过event函数处理。在Qt还设计eventFilter()函数, 可以将一个对象的事件委托给另一个对象监视和处理,实现更灵活的事件过滤;QObject::installEventFilter()函数将自己注册给监视对象,监视对象重新实现QObject::event-Filter()函数,对监视的事件进行处理。

void QObject::installEventFilter(QObject *filterObj)
bool QObject::eventFilter(QObject *watched, QEvent *event)

事件过滤器可以在目标对象之前处理事件,从而使它可以根据需要检查和丢弃事件,可以使用
QObject :: removeEventFilter()函数删除现有的事件过滤器。调用过滤器对象的 eventFilter()实现时,它可以接受或拒绝事件,并允许或拒绝事件的进一步处理,如果所有事件过滤器都允许进一步处理事件(每次返回 false),则事件将发送到目标对象本身。如果其中一个停止处理(返回 true),则目标过滤器和任何以后的事件过滤器将根本看不到该事件。一般我们通过QApplication 或QCoreApplication对象上安装事件过滤器,还可以过滤整个应用程序的所有事件。此类全局事件过滤器在特定于对象的过滤器之前被调用。这是非常强大的功能,但是它也会减慢整个应用程序中每个事件的事件传递速度。

举例:过滤按键事件,如果是按下空格键,就往界面输出信息,自行处理事件。其他事件通过返回QWid-get::eventFilter(object,event),交给父类的eventFilter()函数处理。

bool Widget::eventFilter(QObject *object, QEvent *event)
{
    if (object == this && event->type() == QEvent::KeyPress) //判断是该事件的对象是不是 Widget,并且要是 QEvent::KeyPress
    {
         QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
         if (keyEvent->key() == Qt::Key_Space) 
        {
             QString mesg=QString("空格按键");
             ui->textEdit->append(QString("[%1] %2").arg(QDateTime::currentDateTime().toString("hh:mm:ss")).arg(mesg));
            return true;
        } 
    else
    {
        return false;
    }
    return QWidget::eventFilter(object,event); //返回父类的eventFilter()函数执行结果
}

相关推荐

  1. Qt事件机制

    2024-03-24 17:08:03       37 阅读
  2. Qt消息机制事件--2

    2024-03-24 17:08:03       48 阅读
  3. Qt事件处理机制2-事件函数的传播

    2024-03-24 17:08:03       34 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-24 17:08:03       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-24 17:08:03       100 阅读
  3. 在Django里面运行非项目文件

    2024-03-24 17:08:03       82 阅读
  4. Python语言-面向对象

    2024-03-24 17:08:03       91 阅读

热门阅读

  1. 长链接与短链接的理解

    2024-03-24 17:08:03       33 阅读
  2. Mockito.when返回的list长度为0问题解决方法

    2024-03-24 17:08:03       35 阅读
  3. 用I/O口模拟IIC总线协议遇到的一些问题

    2024-03-24 17:08:03       36 阅读
  4. 对原型模式的理解

    2024-03-24 17:08:03       47 阅读
  5. XXL-JOB通过Postman调试本地任务

    2024-03-24 17:08:03       42 阅读
  6. 对象与继承

    2024-03-24 17:08:03       40 阅读
  7. 【R包开发:包的组件】 第4章 包的元数据

    2024-03-24 17:08:03       35 阅读
  8. PTA-6-16 删除单链表的重复结点

    2024-03-24 17:08:03       39 阅读
  9. 深入浅出:大型语言模型(LLM)的全面解读

    2024-03-24 17:08:03       48 阅读
  10. DOcker in Docker 原理与实战代码详解

    2024-03-24 17:08:03       36 阅读
  11. c语言函数大全(O开头)

    2024-03-24 17:08:03       36 阅读
  12. ARPACK-ng安装教程

    2024-03-24 17:08:03       35 阅读
  13. 游戏开发全过程游戏外包

    2024-03-24 17:08:03       39 阅读
  14. c++ struct解释

    2024-03-24 17:08:03       41 阅读