QT 事件的传递先后顺序

目录

 一、Qt提供5个级别的事件处理和过滤 (从后到先):

1、重新实现事件函数。

2、重新实现QObject::event().

3、安装事件过滤器

4、在 QApplication 上安装事件过滤器。

5、重新实现QApplication 的 notify()方法.

二、event 与 Even Filter

1. event() 简介

2. event 返回值的作用

3. 事件过滤器(Even Filter)


 一、Qt提供5个级别的事件处理和过滤 (从后到先):

1、重新实现事件函数。

比如: mousePressEvent(), keyPressEvent(),   paintEvent() 。

这是最常规的事件处理方法。


2、重新实现QObject::event().

这一般用在Qt没有提供该事件的处理函数时。也就是,我们增加新的事件时。

 

3、安装事件过滤器

installEventFilter()     --      bool eventFilter(QObject *target, QEvent *event)

 

4、在 QApplication 上安装事件过滤器

这之所以被单独列出来是因为: QApplication 上的事件过滤器将捕获应用程序的所有事件,而且***个获得该事件。也就是说事件在发送给其它任何一个event filter之前发送给QApplication的event filter。

 

5、重新实现QApplication 的 notify()方法.

Qt使用 notify()来分发事件。要想在任何事件处理器捕获事件之前捕获事件,***的方法就是重新实现QApplication 的 notify()方法。

二、event 与 Even Filter

1. event() 简介

event 函数的作用就在于 事件的分发,在 even filter 之后执行

bool myWidget::event(QEvent *e)
{
    if (e->type() == QEvent::KeyPress) 
    {
        //将QEvent对象转换为真正的QKeyEvent对象
        QKeyEvent *keyEvent = static_cast(e);
        if (keyEvent->key() == Qt::Key_Tab) 
        {
            qDebug() << "You press tab.";
            return true;
        }
    }
    //按照原来的流程来进行事件的分发
    return QWidget::event(e);
}

2. event 返回值的作用

如果传入的事件已被识别并且处理,则需要返回 true,否则返回 false。如果返回值是 true,那么 Qt 会认为这个事件已经处理完毕,不会再将这个事件发送给其它对象,而是会继续处理事件队列中的下一事件。

若返回 父类的 event,即 return QWidget::event(e); 则还会调用 父组件。

Qt系统在处理事件时,有一种机制叫 事件传播机制。也就是说,在子组件(比如说一个QButton)中发生的事件,调用了子组件的event函数之后,还会 调用父组件(比如说QWidget)的 event 函数。event函数的 返回值 就用于控制这样的一个过程。

QT 事件的传递先后顺序_第1张图片

需要注意的是,重写event函数之后最好返回父类的event函数来处理其他的事件分发,不然就只能处理自己定义的事件。

bool myTextEdit::event(QEvent *e)
{
    if (e->type() == QEvent::KeyPress) 
    {
        //将QEvent对象转换为真正的QKeyEvent对象
        QKeyEvent *keyEvent = static_cast(e);
        if (keyEvent->key() == Qt::Key_Tab) 
        {
            qDebug() << "You press tab.";
            return true;
        }
    }
    //直接返回false
    return false;
}

在这个例子中,因为没有调用父类QTextEditevent函数,所以只能处理Tab的情况,你再按其他按键就啥反应都没有了。同样,事件也不能进行传播。

3. 事件过滤器(Even Filter)

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

函数的返回值也是bool类型,作用跟even函数类似,返回true为不再转发,false则让其继续被处理

class MainWindow : public QMainWindow
{
public:
    MainWindow();
protected:
    bool eventFilter(QObject *obj, QEvent *event);
private:
    QTextEdit *textEdit;
};
 
MainWindow::MainWindow()
{
    textEdit = new QTextEdit;
    setCentralWidget(textEdit);
    
    textEdit->installEventFilter(this);
}
 
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
    if (obj == textEdit) 
    {
        if (event->type() == QEvent::KeyPress) 
        {
            QKeyEvent *keyEvent = static_cast(event);
            qDebug() << "you press" << keyEvent->key();
            //事件不再进行传播,拦截
            return true;
        } 
        else
        {
            return false;//继续传播
        }
    } 
    else 
    {
        //当不确定是否继续传播时,按照父类的方法来处理
        //即调用父类的evenFilter函数
        return QMainWindow::eventFilter(obj, event);

        //也可直接 return false; 不进行拦截, 且不继续传播

    }
}

 

你可能感兴趣的:(Qt)