自学内容网 自学内容网

Qt事件系统

Qt的事件系统通过QEvent对象表示事件并传递给QObject实例。事件包括窗口系统事件、计时器事件等,由QEvent::Type定义类型。事件处理通过事件处理程序如event()和特定事件处理函数如paintEvent()进行。事件过滤器允许对象拦截和处理其他对象的事件。发送事件可以通过sendEvent()立即处理或postEvent()异步处理。自定义事件需要定义事件编号和可能的QEvent子类。

事件系统

在Qt中,事件是从抽象QEvent类派生的对象,它们表示发生在应用程序内部或由于应用程序需要了解的外部活动而发生的事情。事件可以由QObject子类的任何实例接收和处理,但它们与小部件尤其相关。本文档介绍了在典型应用程序中如何传递和处理事件。

当事件发生时,Qt通过构造适当的QEvent子类的实例来创建一个事件对象来表示它,并通过调用其event()函数将其传递到QObject的特定实例(或其子类之一)。

此函数不处理事件本身;它不会处理事件。根据所传递事件的类型,它为该特定类型的事件调用事件处理程序,并根据该事件被接受还是忽略发送响应。

一些事件,例如QMouseEvent和QKeyEvent,来自窗口系统。一些,例如QTimerEvent,来自其他来源;有些来自应用程序本身。

Event类型

多数事件类型都有特殊的类,尤其是QResizeEvent,QPaintEvent,QMouseEvent,QKeyEvent和QCloseEvent。每个类都将QEvent子类化,并添加特定于事件的函数。例如,QResizeEvent添加了size()和oldSize()来使小部件能够发现其尺寸如何被更改。

一些类支持不止一种实际的事件类型。QMouseEvent支持鼠标按键按下,双击,移动和其他相关操作。

每个事件都有一个关联的类型,在QEvent::Type中定义,并且可以用作运行时类型信息的便捷来源,以快速确定构造给定事件对象的子类。

由于程序需要以各种复杂的方式做出反应,因此Qt的事件传递机制非常灵活。QCoreApplication :: notify()的文档简明扼要地讲述了整个故事。

时间处理程序

传递事件的常用方法是调用虚拟函数。如通过调用QWidget::paintEvent()来传递QPaintEvent。该虚函数负责适当地做出反应,通常通过重新绘制窗口小部件来实现。如果没有在虚拟函数的实现中执行所有必要的工作,则可能需要调用基类的实现。
例如,处理自定义复选框小部件上的鼠标左键单击,同时将所有其他按钮单击传递给基本QCheckBox类:

void MyCheckBox::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) 
    {
        // handle left mouse button
    } else 
    {
        // pass on other buttons to base class
        QCheckBox::mousePressEvent(event);
    }
}

如果要替换基类的功能,则必须自己实现所有功能。但如果只想扩展基类的功能,则可以实现所需的功能并调用基类以获取不想处理的任何情况下的默认行为。

有时,没有此类特定于事件的功能或特定于事件的功能还不够。常见的示例涉及按下Tab键。通常,QWidget会拦截这些以移动键盘焦点,但一些小部件需要自己使用Tab键。

这些对象可以重新实现常规事件处理程序QObject :: event(),并且可以在常规处理之前或之后进行事件处理,或者可以完全替换该函数。一个既解释Tab又具有特定于应用程序的自定义事件的非常不寻常的小部件,可能包含以下event():

bool MyWidget::event(QEvent *event)  
{  
    if (event->type() == QEvent::KeyPress) 
    {  
        QKeyEvent *ke = static_cast<QKeyEvent *>(event);  
        if (ke->key() == Qt::Key_Tab) 
        { 
            // special tab handling here  
            return true;  
        }  
    } 
    else if (event->type() == MyCustomEventType) 
    { 
        // 假设 MyCustomEventType 已经定义  
        MyCustomEvent *myEvent = static_cast<MyCustomEvent *>(event);  
        // custom event handling here  
        return true;  
    }  
  
    return QWidget::event(event);  
}

注:对于所有未处理的情况,仍会调用QWidget::event(),并且返回值指示是否处理了事件。true值会阻止事件上的其他对象被发送。

事件过滤器

有时,一个对象需要查看并可能拦截传递给另一个对象的事件。如,对话框通常要过滤某些小部件的按键;修改返回键处理。

QObject::installEventFilter()通过设置事件过滤器,造成提名过滤器对象接收的事件为在其目标对象的QObject::eventFilter()。事件过滤器可以在目标对象之前处理事件,从而使它可以根据需要检查和丢弃事件。可以使用QObject::removeEventFilter()删除现有的事件过滤器。

调用过滤器对象的eventFilter()实现时,它可以接受或拒绝事件,并允许或拒绝事件的进一步处理。如果所有事件过滤器都允许进一步处理事件(每次返回false),则事件将发送到目标对象本身。如果其中一个停止处理(返回true),则目标过滤器和任何以后的事件过滤器将根本看不到该事件。

bool FilterObject::eventFilter(QObject *object, QEvent *event)  
{  
    // 检查事件是否来自目标对象且事件类型是KeyPress  
    if (object == target && event->type() == QEvent::KeyPress) 
    {  
        QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);  
          
        // 检查按键是否是Tab键  
        if (keyEvent->key() == Qt::Key_Tab) 
        {  
            // 特殊Tab键处理  
            return true; // 表示事件已被处理  
        }  
    }  
      
    // 如果事件不是来自目标对象、不是KeyPress事件或不是Tab键,则继续传递事件  
    return QObject::eventFilter(object, event); // 调用基类的eventFilter,允许事件继续传播  
}

上面代码显示了另一种拦截发送到特定目标小部件的Tab键按下事件的方法。在这种情况下,过滤器将处理相关事件并返回true以停止对其进行进一步处理。所有其他事件都将被忽略,并且过滤器返回false以允许通过安装在其上的任何其他事件过滤器将它们发送到目标窗口小部件。

通过在QApplication或QCoreApplication对象上安装事件过滤器,还可以过滤整个应用程序的所有事件。此类全局事件过滤器在特定于对象的过滤器之前被调用。这是非常强大的功能,但它会减慢整个应用程序中每个事件的事件传递速度。通常应使用所讨论的其它技术来代替。

发送事件

许多应用程序都希望创建并发送自己的事件。可以通过构造合适的事件对象并使用QCoreApplication::sendEvent()和QCoreApplication::postEvent()发送事件,以与Qt自己的事件循环完全相同的方式发送事件。

sendEvent()立即处理事件。返回时,事件过滤器和/或对象本身已经处理了该事件。对于许多事件类,有一个称为isAccepted()的函数,该函数告诉程序员该事件是被最后一个调用的处理程序接受还是拒绝。

postEvent()将事件发布到队列中,以供以后分派。下次Qt的主事件循环运行时,它将分派所有已发布的事件,并进行一些优化。例如,如果有多个调整大小事件,它们将被压缩为一个。这同样适用于绘画事件:QWidget::update()调用postEvent(),通过避免多次重新绘画来消除闪烁并提高速度。

postEvent()也用于对象初始化期间,因为通常会在对象初始化完成后很快分派已发布的事件。在实现窗口小部件时,重要的是要意识到事件可以在其生命周期的很早就交付,因此,在其构造函数中,请确保在有可能接收事件之前尽早初始化成员变量。

要创建自定义类型的事件,您需要定义一个事件编号,该事件编号必须大于QEvent::User,并且可能需要子类QEvent才能传递有关自定义事件的特定信息。


原文地址:https://blog.csdn.net/wk131421/article/details/142951045

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