QT开发(六十三)——QT事件机制分析

QT开发(六十三)——QT事件机制分析

1、事件机制

    事件是由系统或者QT平台自己在不一样的时刻发出的。当用户按下鼠标、敲下键盘,或者是窗口须要从新绘制的时候,都会发出一个相应的事件。一些事件在对用户操做作出响应时发出,如键盘事件等;另外一些事件则是由系统自动发出,如计时器事件。安全

    事件的出现,使得程序代码不会按照原始的线性顺序执行。线性顺序的程序设计风格不适合处理复杂的用户交互,如用户交互过程当中,用户点击“打开文件”将开始执行打开文件的操做,用户点击“保存文件”将开始执行保存文件的操做。用户交互过程当中进行什么样的操做是由用户决定的,程序设计时没法事先预测,同时用户的操做都会发出相应的事件,所以用户交互的程序设计中程序的执行顺序再也不是线性的,而是由一个个事件驱动着程序继续执行,若是没有事件,程序将阻塞,不执行任何代码。app

    QT中,使用QT组件时,一般不会把主要精力放在事件上。更可能是关心事件关联的信号。好比,对于QPushButton的鼠标点击,不须要关心这个鼠标点击事件,而是关心clicked()信号的发出。但QT中的事件和信号槽却并非能够相互替代的。信号由具体的对象发出,信号一旦发出,而后会立刻交给由connect()函数链接的槽进行处理;而对于事件,QT使用一个事件队列对全部发出的事件进行维护,当新的事件产生时,会被追加到事件队列的尾部,前一个事件完成后,取出后面的事件进行处理,而且QT的事件也能够不进入事件队列,而是直接处理。事件则可使用“事件过滤器”进行过滤,对于有些事件进行额外的处理,其它的事件则不关心。异步

    一般,若是使用组件,关心的是信号槽;若是自定义组件,关心的是事件。由于能够经过事件来改变组件的默认操做。好比,若是要自定义一个可以响应鼠标事件的EventLabel,就须要重写QLabel的鼠标事件,作出指望的操做,有可能还得在恰当的时候发出一个相似按钮的clicked()信号(若是指望让EventLabel可以被其它组件使用)或者其它的信号。ide

    QT程序须要在main()函数建立一个QCoreApplication对象,而后调用exec()函数。exec()函数就是开始QT的事件循环。执行exec()函数后,程序将进入事件循环来监听应用程序的事件。当事件发生时,QT将建立一个事件对象。QT中全部事件类都继承于QEvent。在事件对象建立完毕后,QT将建立的事件对象传递给QObject的event()函数。event()函数并不直接处理事件,而是按照事件对象的类型分派给特定的事件处理函数(event handler)。函数

    在全部组件的父类QWidget中,定义了不少事件处理的回调函数,如keyPressEvent()、keyReleaseEvent()、mouseDoubleClickEvent()、mouseMoveEvent()、mousePressEvent()、mouseReleaseEvent()等。若是要在自定义组件中对事件进行处理,须要在子类中从新实现事件处理函数。post

    QWidget组件有一个mouseTracking属性,用于设置是否追踪鼠标。只有鼠标被追踪时,mouseMoveEvent()才会发出。若是mouseTracking是 false(默认),QWidget组件在至少一次鼠标点击后才可以被追踪,即在鼠标点击后才可以发出mouseMoveEvent()事件。若是设置mouseTracking为true,则mouseMoveEvent()直接能够被发出。ui

2、事件处理

1、自定义类的事件处理函数

事件处理包括事件接受和忽略。this

实例代码:spa

CustomButton.h文件:线程

#ifndef CUSTOMBUTTON_H
#define CUSTOMBUTTON_H
 
#include <QPushButton>
#include <QDebug>
 
class CustomButton : public QPushButton
{
public:
    CustomButton(QWidget* parent = 0);
protected:
    void mousePressEvent(QMouseEvent *event);
private slots:
    void onButton();
};
 
#endif // CUSTOMBUTTON_H

CustomButton.cpp文件:

#include "CustomButton.h"
#include <QMouseEvent>
 
CustomButton::CustomButton(QWidget* parent):QPushButton(parent)
{
    connect(this, &CustomButton::clicked, this, &CustomButton::onButton);
}
 
void CustomButton::onButton()
{
  qDebug() << "child clicked";
}
 
void CustomButton::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
    {
        qDebug() << "Left press";
    }
    else
    {
        QPushButton::mousePressEvent(event);
    }
}

Mainc.cpp文件:

#include "CustomButton.h"
#include <QApplication>
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    CustomButton button;
    button.setText("button");
    button.show();
 
    return a.exec();
}

    自定义类CustomButton继承自QPushButton,重写了mousePressEvent()函数,即鼠标按下事件处理函数。mousePressEvent()函数中,若是鼠标按下的是左键,则打印Left press”字符串,不然,调用父类的同名函数。槽函数onButton()打印“child clicked”。

    编译运行程序,鼠标点击按钮后打印出Left press”字符串,没有打印出“child clicked”字符串。

    缘由在于自定义类CustomButton的事件处理函数mousePressEvent()覆盖了父类QPushButton相应的事件处理函数。父类QPushButtonmousePressEvent()事件处理函数会发出clicked()信号,自定义类CustomButton实现则不发出clicked()信号。所以,自定义类CustomButton对象在鼠标按下时没有发出clicked()信号,链接的槽函数onButton()不会执行。

自定义类中重写父类的事件处理函数时会覆盖父类相应的事件处理函数,父类的事件处理函数中包含的操做(如发出某些信号)也将会被覆盖。所以当重写事件回调函数时,必须注意是否须要经过调用父类的同名函数来确保原有实现仍能进行。

    经过调用父类的同名函数,能够把QT的事件传递当作链状:若是子类没有处理这个事件,就会继续向其父类传递。Qt 的事件对象有两个函数:accept()和ignore()。accept()通知QT平台,事件处理函数要处理这个事件;ignore()则通知QT平台,事件处理函数不处理这个事件。在事件处理函数中,可使用isAccepted()来查询某个事件是否是已经被接受。

    若是一个事件处理函数调用了一个事件对象的accept()函数,这个事件就不会被继续传播给其父组件;若是事件对象调用了事件的ignore()函数,QT平台会从其父组件中寻找另外的接受者。

    一般不多会使用accept()和ignore()函数,若是但愿忽略事件,只要调用父类的相应事件处理函数便可。因为没法确认父类中相应的事件处理函数有没有额外的操做,若是在子类中直接使用ignore()函数忽略事件,QT会去寻找其余的接受者,父类的操做会被忽略(由于没有调用父类的同名函数),这可能会有潜在的危险。为了不子类去调用accept()和ignore()函数,而是尽可能调用父类实现,QT作了特殊的设计:事件对象默认是accept的,而做为全部组件的父类QWidget的默认实现则是调用ignore()。所以,若是子类从新实现事件处理函数,不调用QWidget的默认实现,就等于接受事件;若是要忽略事件,只需调用QWidget的默认事件处理函数实现。

    QT5中QWidget的mousePressEvent()函数的源码实现以下:

void QWidget::mousePressEvent(QMouseEvent *event)
{
    event->ignore();
    if ((windowType() == Qt::Popup)) 
    {
        event->accept();
        QWidget* w;
        while ((w = QApplication::activePopupWidget()) && w != this)
        {
            w->close();
            if (QApplication::activePopupWidget() == w)
                w->hide(); // hide at least
        }
        if (!rect().contains(event->pos()))
        {
            close();
        }
    }
}

    若是子类没有重写mousePressEvent()函数,QT会默认忽略这个事件,继续寻找下一个事件接收者。若是在子类的mousePressEvent()函数中直接调用了accept()或者ignore(),而没有调用父类相应的事件处理函数,QWidget::mousePressEvent()函数中关于Popup判断的代码就不会被执行,所以可能会出现莫名其妙的怪异现象。

二、事件的传播

CustomButton.h文件:

#ifndef CUSTOMBUTTON_H
#define CUSTOMBUTTON_H
 
#include <QPushButton>
 
class CustomButton : public QPushButton
{
    Q_OBJECT
public:
    CustomButton(QWidget* parent = 0);
protected:
    void mousePressEvent(QMouseEvent *event);
};
 
#endif // CUSTOMBUTTON_H

CustomButton.cpp文件:

#include "CustomButton.h"
#include <QMouseEvent>
#include <QDebug>
 
CustomButton::CustomButton(QWidget* parent):QPushButton(parent)
{
}
 
void CustomButton::mousePressEvent(QMouseEvent *event)
{
   event->ignore();
   qDebug() << "CustomButton";
}

CustomButtonEx.h文件:

#ifndef CUSTOMBUTTONEX_H
#define CUSTOMBUTTONEX_H
 
#include "CustomButton.h"
 
class CustomButtonEx : public CustomButton
{
    Q_OBJECT
public:
    CustomButtonEx(QWidget* parent = 0);
protected:
    void mousePressEvent(QMouseEvent *event);
};
 
#endif // CUSTOMBUTTONEX_H

CustomButtonEx.cpp文件:

 

#include "CustomButtonEx.h"
#include "CustomWidget.h"
#include <QMouseEvent>
#include <QDebug>
 
CustomButtonEx::CustomButtonEx(QWidget* parent):CustomButton(parent)
{
}
 
void CustomButtonEx::mousePressEvent(QMouseEvent *event)
{
    event->ignore();
    qDebug() << "CustomButtonEx";
}

CustomWidget.h文件:

#ifndef CUSTOMWIDGET_H
#define CUSTOMWIDGET_H
 
#include <QWidget>
 
class CustomWidget : public QWidget
{
    Q_OBJECT
public:
    explicit CustomWidget(QWidget *parent = 0);
protected:
    void mousePressEvent(QMouseEvent *event);
};
 
#endif // CUSTOMWIDGET_H

CustomWidget.cpp文件:

#include "CustomWidget.h"
#include <QMouseEvent>
#include <QDebug>
 
CustomWidget::CustomWidget(QWidget *parent) : QWidget(parent)
{
}
 
void CustomWidget::mousePressEvent(QMouseEvent *event)
{
    qDebug() << "CustomWidget";
}

Main.cpp文件:

#include "CustomButton.h"
#include "CustomButtonEx.h"
#include "CustomWidget.h"
#include <QApplication>
#include <QHBoxLayout>
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    CustomWidget* customWidget = new CustomWidget();
 
    CustomButton* custombutton = new CustomButton(customWidget);
    custombutton->setText("CustomBuuton");
    CustomButtonEx* custombuttonex = new CustomButtonEx(customWidget);
    custombuttonex->setText("CustomButtonEx");
 
    QHBoxLayout* layout = new QHBoxLayout(customWidget);
    layout->addWidget(custombutton);
    layout->addWidget(custombuttonex);
    customWidget->setLayout(layout);
 
    customWidget->show();
    return a.exec();
}

    在自定义组件CustomWidget内放置两个按钮对象:CustomButton和CustomButtonEx,每个类都重写了mousePressEvent()函数

    若是在CustomButtonEx的mousePressEvent()中调用event->accept(),鼠标按下事件将不会传播到父组件CustomWidget,只会打印出“CustomButtonEx”;若是CustomButtonEx的mousePressEvent()中调用event->ignore(),鼠标按下事件会继续传播到父组件CustomWidget,会打印出“CustomButtonEx”、“CustomWidget”。因为CustomWidgetmousePressEvent()函数中并未调用event->accept(),所以鼠标按下事件传播到CustomWidget组件为止。

    CustomButtonEx的事件传播给了父组件CustomWidget,而不是父类CustomButton。事件的传播是在组件层次上面的,而不是依靠类继承机制。

    在窗口关闭事件处理函数closeEvent必须使用accept()和ignore()函数。对于窗口关闭QCloseEvent事件,调用accept()意味着QT会中止事件的传播,窗口关闭;调用ignore()则意味着事件继续传播,即阻止窗口关闭。

void CustomWidget::closeEvent(QCloseEvent *event)
{
 
    bool exit = QMessageBox::question(this,
                     tr("Quit"),
                     tr("Are you sure to quit this application?"),
                     QMessageBox::Yes | QMessageBox::No,
                     QMessageBox::No) == QMessageBox::Yes;
    if (exit)
    {
        event->accept();
    }
    else
    {
        event->ignore();
    }
}

3、事件分发

    事件对象建立完毕后,QT将这个事件对象传递给QObject的event()函数。event()函数并不直接处理事件,而是将这些事件对象按照它们不一样的类型分发给不一样的事件处理器(event handler)。

    event()函数主要用于事件的分发。若是指望在事件分发前作一些操做,能够重写event()函数

    在QWidget组件中监听某个按键按下事件实现以下:

bool CustomWidget::event(QEvent *event)
{
    if (event->type() == QEvent::KeyPress)
    {
        QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
        if (keyEvent->key() == Qt::Key_K)
        {
            qDebug() << "You press K.";
            return true;
        }
    }
    return QWidget::event(event);
}

    CustomWidget继承自QWidget,重写了event()函数,event()函数有一个QEvent对象做为参数,是须要转发的事件对象。函数返回值是 bool类型。若是传入的事件已被识别而且处理,则须要返回 true,不然返回 false。若是返回值是 true,而且事件对象设置了accept(),那么QT会认为这个事件已经处理完毕,不会再将这个事件发送给其它组件,而是会继续处理事件队列中的下一事件。注意,在event()函数中,调用事件对象的accept()和ignore()函数是没有做用的,不会影响到事件的传播。

    经过使用QEvent::type()函数能够检查事件的实际类型,其返回值是QEvent::Type类型的枚举。处理完本身感兴趣的事件后,能够直接返回 true,表示已经对此事件进行了处理;对于其它不关心的事件,则须要调用父类的event()函数继续转发,不然自定义组件就只能处理咱们感兴趣的事件,其它事件将被丢弃。

    QT5 中QObject::event()函数的源代码以下:

bool QObject::event(QEvent *e)
{
    switch (e->type()) 
    {
    case QEvent::Timer:
        timerEvent((QTimerEvent*)e);
        break;
    case QEvent::ChildAdded:
    case QEvent::ChildPolished:
    case QEvent::ChildRemoved:
        childEvent((QChildEvent*)e);
        break;
        // ...
    default:
        if (e->type() >= QEvent::User) 
        {
            customEvent(e);
            break;
        }
        return false;
    }
    return true;
}

    QT使用QEvent::type()判断事件类型,调用特定的事件处理器实现事件的分发。好比,若是event->type()返回值是QEvent::Timer,则调用timerEvent()函数。

4事件过滤器

    QT建立了QEvent事件对象后,会调用QObject的event()函数处理事件的分发。虽然能够在event()函数中实现拦截的操做,但event()函数有两大缺点。

    A、event()函数是 protected的,须要继承已有类。若是组件不少,就须要重写不少个event()函数。

 B、event()函数虽然能够拦截事件,但其实组件是接收到了事件的。

为了解决event()函数拦截事件的缺陷,QT提供了另一种方式来实现对事件的拦截:事件过滤器。

    QObject有一个eventFilter()函数,用于创建事件过滤器。

    virtual bool QObject::eventFilter(QObject * watched, QEvent * event);

    事件过滤器会检查接收到的事件。若是这个事件是感兴趣的类型,就进行处理;若是不是,就继续转发。eventFilter函数返回一个bool类型,若是想将参数event过滤出来,好比不想让它继续转发,就返回true,不然返回false。事件过滤器的调用时间是目标对象(watched对象)接收到事件对象前。若是在事件过滤器中中止了某个事件,那么watched对象以及之后全部的事件过滤器都不会知道这个事件。

bool CustomWidget::eventFilter(QObject *watched, QEvent *event)
{
    if (watched == this && event->type() == QEvent::KeyPress)
    {
        QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
        if (keyEvent->key() == Qt::Key_K)
        {
            qDebug() << "eventFilter: You press K.";
            return true;
        }
        else
        {
            return false;
        }
    }
    return false;
}

    自定义类CustomWidget重写了eventFilter()函数。为了过滤特定组件上的事件,首先须要判断这个组件对象是否是感兴趣的组件,而后判断要过滤事件的类型。若是是要过滤的事件则直接返回true,即过滤掉这个事件,其余事件仍是要继续处理,因此返回false。对于其它的组件,因为不保证是否是还有过滤器,最保险的办法是调用父类的eventFilter()函数,保证父对象上面设置的事件过滤器能够被调用。

    eventFilter()函数至关于建立了过滤器,要使过滤器生效须要安装过滤器。安装过滤器须要调用QObject::installEventFilter()函数。

    void QObject::installEventFilter (QObject * filterObj);

    filterObj是过滤器对象,即事件过滤器所属的类对象。

CustomWidget::CustomWidget(QWidget *parent) : QWidget(parent)
{
    this->installEventFilter(this);
}

    建立事件过滤器并安装事件过滤器后,在CustomWidget按下鼠标时,鼠标事件将会被过滤,所以会打印出“eventFilter: You press K.”字符串,mousePressEvent()函数将不会被调用,不会打印出“CustomWidget”字符串。

    eventFilter()函数是QObject的一个成员函数,所以,任意QObject均可以做为事件过滤器(若是没有重写eventFilter()函数,事件过滤器是没有任何做用的,由于默认什么都不会过滤)。已经存在的过滤器则能够经过QObject::removeEventFilter()函数移除。

    能够向一个对象上面安装多个事件处理器,只要调用屡次installEventFilter()函数。若是一个对象存在多个事件过滤器,那么,最后一个安装的会第一个执行,也就是后进先执行的顺序。

    事件过滤器的强大之处在于能够为整个应用程序添加一个事件过滤器。installEventFilter()函数是QObject的函数,QApplication或者QCoreApplication对象都是QObject的子类,所以,能够向QApplication或者QCoreApplication添加事件过滤器。

    若是使用installEventFilter()函数给一个对象安装事件过滤器,那么该事件过滤器只对该对象有效,只有这个对象的事件须要先传递给事件过滤器的eventFilter()函数进行过滤,其它对象不受影响。若是给QApplication对象安装事件过滤器,那么该过滤器对程序中的每个对象都有效,任何对象的事件都是先传给eventFilter()函数。这种全局的事件过滤器将会在全部其它特性对象的事件过滤器以前调用。尽管很强大,但这种行为会严重下降整个应用程序的事件分发效率。所以,除非是不得不使用的状况,不然的话不该该这么作。

    注意,若是在事件过滤器中delete了某个接收组件,务必将函数返回值设为 true。不然,QT仍是会将事件分发给这个接收组件,从而致使程序崩溃。

    事件过滤器和被安装过滤器的组件必须在同一线程,不然,过滤器将不起做用。若是在安装过滤器以后,两个组件到了不一样的线程,那么,只有等到两者从新回到同一线程的时候过滤器才会有效。QT中,对象建立以后可使用moveToThread()函数将一个对象移动到另外的线程。

五、事件处理总结

QT事件处理的层次:

A、重写paintEvent()、mousePressEvent()等事件处理函数,是最普通、最简单的形式,同时功能也最简单。

B、重写event()函数。event()函数是全部对象的事件入口,QObject和QWidget中的实现,默认是把事件传递给特定的事件处理函数。

C、在特定对象上面安装事件过滤器,事件过滤器仅过滤该对象接收到的事件。

D、QCoreApplication::instance()上安装事件过滤器。事件过滤器将过滤全部对象的全部事件。全局的事件过滤器能够看到disabled组件上面发出的鼠标事件。全局过滤器只能用在主线程。

E、重写QCoreApplication::notify()函数。与全局事件过滤器同样,提供彻底控制,而且不受线程的限制。但全局范围内只能有一个被使用(由于QCoreApplication是单例的)。

CustomWidget.h文件:

#ifndef CUSTOMWIDGET_H
#define CUSTOMWIDGET_H
 
#include <QWidget>
 
class CustomWidget : public QWidget
{
    Q_OBJECT
public:
    explicit CustomWidget(QWidget *parent = 0);
protected:
    void mousePressEvent(QMouseEvent *event);
    void closeEvent(QCloseEvent *event);
    bool event(QEvent *event);
    bool eventFilter(QObject *watched, QEvent *event);
 
};
 
#endif // CUSTOMWIDGET_H

CustomWidget.cpp文件:

#include "CustomWidget.h"
#include <QMouseEvent>
#include <QDebug>
 
CustomWidget::CustomWidget(QWidget *parent) : QWidget(parent)
{
    this->installEventFilter(this);
}
 
void CustomWidget::mousePressEvent(QMouseEvent *event)
{
    qDebug() << "CustomWidget::mousePressEvent";
}
 
bool CustomWidget::event(QEvent *event)
{
    if (event->type() == QEvent::MouseButtonPress)
    {
        qDebug() << "CustomWidget::event";
    }
    return QWidget::event(event);
}
 
bool CustomWidget::eventFilter(QObject *watched, QEvent *event)
{
    if (event->type() == QEvent::MouseButtonPress)
    {
        qDebug() << "CustomWidget::eventFilter";
    }
    return false;
}

Main.cpp文件:

#include "CustomWidget.h"
#include <QApplication>
#include <QDebug>
 
class EventFilter : public QObject
{
public:
    EventFilter(QObject *watched, QObject *parent = 0) :
        QObject(parent),
        m_watched(watched)
    {
    }
 
    bool eventFilter(QObject *watched, QEvent *event)
    {
        if (watched == m_watched)
        {
            if (event->type() == QEvent::MouseButtonPress)
            {
                qDebug() << "QApplication::eventFilter";
            }
        }
        return false;
    }
 
private:
    QObject *m_watched;
};
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    CustomWidget customWidget;
    a.installEventFilter(new EventFilter(&customWidget, &customWidget));
    customWidget.show();
    return a.exec();
}

    按下鼠标键后,打印出字符串:

QApplication::eventFilter

CustomWidget::eventFilter

CustomWidget::event

CustomWidget::mousePressEvent

    全局事件过滤器被第一个调用,组件对象上的事件过滤器第二个被调用,event()函数第三个调用,特定的事件处理函数第四个调用。

3、自定义事件

    事件的分发既能够是同步的,又能够是异步的,而信号槽的回调老是同步的。而且事件可使用过滤器。

1、自定义事件的类型

    QT自定义事件须要继承QEvent。QEvent提供一个QEvent::Type类型的参数,做为自定义事件的类型值。

    QEvent::Type是QEvent定义的一个枚举。须要注意的是自定义事件类型不能和已经存在的type值重复,不然会有不可预料的错误发生,由于系统会将新增长的自定义事件当作系统事件进行派发和调用。QT中,系统保留0 – 999的值,自定义事件的type要大于 999。QT定义了两个边界值:QEvent::User和QEvent::MaxUser,自定义事件的type应该在两个值的范围之间。其中,QEvent::User的值是1000,QEvent::MaxUser的值是65535。经过这两个枚举值,能够保证自定义的事件类型不会覆盖系统定义的事件类型。但并不能保证自定义事件相互之间不会被覆盖。为了不自定义事件间的相互覆盖,QT提供了一个函数:registerEventType(),用于自定义事件的注册。

    static int QEvent::registerEventType ( int hint = -1 );

    registerEventType函数是static的,可使用QEvent类直接调用。函数返回值是向系统注册的新的Type类型的值。若是hint是合法的,hint不会发生任何覆盖(系统的以及其它自定义事件的),则会直接返回这个值;不然,系统会自动分配一个合法值并返回。使用registerEventType函数便可完成type 值的指定。registerEventType函数是线程安全的,没必要另外添加同步。

2、事件的发送方式

    能够在自定义事件中添加所须要的数据,而后进行事件的发送。

    QT提供了两种事件发送方式:

    A、非阻塞式发送

    static bool QCoreApplication::sendEvent(QObject *receiver,QEvent *event);

    直接将event事件发送给receiver接收者,使用的是QCoreApplication::notify()函数。函数返回值就是事件处理函数的返回值。在事件被发送的时候,event对象并不会被销毁。一般会在栈上建立event对象,例如:

    QMouseEvent event(QEvent::MouseButtonPress, pos, 0, 0, 0);

    QApplication::sendEvent(receiver, &event);

    B、阻塞式发送

    static void QCoreApplication::postEvent(QObject *receiver,QEvent *event);

    将event事件及其接收者receiver一同追加到事件队列中,函数当即返回。

由于post事件队列会持有事件对象,而且在其post的时候将其delete掉,所以,必须在堆上建立event对象。当对象被发送以后,再试图访问event对象就会出现问题(由于post后,event对象就会被delete)。

    当控制权返回到主线程循环时,保存在事件队列中的全部事件都经过notify()函数发送出去。

    事件会根据post的顺序进行处理。若是想要改变事件的处理顺序,能够考虑为其指定一个优先级。默认的优先级是Qt::NormalEventPriority。

    postEvent函数是线程安全的。

    static void QCoreApplication::sendPostedEvents(QObject *receiver,int event_type);

    sendPostedEvents函数的做用是将事件队列中的接收者为receiver,事件相似为event_type的全部事件当即发送给receiver进行处理。须要注意的是,来自窗口系统的事件并不禁sendPostedEvents函数进行处理,而是processEvent()。

3、自定义事件处理函数

    自定义事件的处理既能够定义一个自定义事件处理函数,也能够在event()函数中直接处理

void CustomWidget::customEvent(QEvent *event)
{
    CustomEvent *customEvent = static_cast<CustomEvent *>(event);
    // ...
}
 
bool CustomWidget::event(QEvent *event) 
{
    if (event->type() == CustomEventType) 
    {
        CustomEvent *myEvent = static_cast<CustomEvent *>(event);
        // processing...
        return true;
    }
    return QWidget::event(event);
}
相关文章
相关标签/搜索