我是靠谱客的博主 瘦瘦狗,最近开发中收集的这篇文章主要介绍Qt事件过滤器,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

1、事件过滤器

用于拦截传递到目标对象的事件,这样可以实现监视目标对象事件的作用。

2、Qt 实现事件过滤器的步骤如下:

①、 Qt 调用
void QObject::installEventFilter (QObject* filterObj)
把 filterObj 对象设置安装(或注册)为事件过滤器, filterObj 也称为过滤器对象。 事件
过滤器通常在构造函数中进行注册。
②、 在上一步注册的 filterObj 对象,通过调用
bool QObject::eventFilter(QObject* obj, QEvent* e);
来接收拦截到的事件。也就是说拦截到的事件在 filterObj 对象中的 eventFilter 函数中
处理。 eventFilter 的第一个参数 obj 指向的是事件本应传递到的目标对象。
③、 使用 QObject::removeEventFilter(QObject *obj)函数可以删除事件过滤器。

3、 事件过滤器处理事件的规则

①、 过滤器对象的 eventFilter()函数可以接受或拒绝拦截到的事件,若该函数返回 false,
则表示事件需要作进一步处理,此时事件会被发送到目标对象本身进行处理(注意:
这里并未向父对象进行传递),若 eventFilter()返回 true,则表示停止处理该事件,此
时目标对象和后面安装的事件过滤器就无法获得该事件。

demo:

#include <QApplication>
#include<QWidget>
#include<QMouseEvent>
#include<QPushButton>
#include<QObject>
#include <iostream>
using namespace std;

class A:public QObject{
public: //该类的对象用作过滤器对象,使用事件过滤器需继承 QObject
    bool eventFilter(QObject *w, QEvent *e)
    {
        if(e->type()==QEvent::MouseButtonPress)
        {
            cout<<w->objectName().toStdString(); //验证 w 为事件本应到达的目标对象
            cout<<"=Ak"<<endl;
            return 1; //返回 1 表示该事件不再进一步处理
        }
        return 0;
    } /*返回 0 表示其余事件交还给目标对象处理, 本例应返回 0,否则添加了该
                                      过滤器的安钮会无法显示。 */
};
class B:public A{
public: //继承自类 A
    bool eventFilter(QObject *w, QEvent *e)
    {
        if(e->type()==QEvent::MouseButtonPress)
        {
            cout<<w->objectName().toStdString()<<"=Bk"<<endl;
            return 0;
        }
        return 0;
    }
};
class C:public QWidget
{
public:
    void mousePressEvent(QMouseEvent *e)
    {
        cout<<"Ck"<<endl;
    }
};
class D:public QPushButton
{
public:
    void mousePressEvent(QMouseEvent *e)
    {
        cout<<"DK"<<endl;
    }
};
int main(int argc, char *argv[])
{
    QApplication a(argc,argv);
    //创建对象,注意:本例父对象应先创建,以避免生命期过早结束
    A ma; B mb; C mc; D *pd=new D; D *pd1=new D;
    pd->setText("AAA");
    pd->move(22,22);
    pd1->setText("BBB");
    pd1->move(99,22);
    //设置对象名
    ma.setObjectName("ma");
    mb.setObjectName("mb");
    mc.setObjectName("mc");
    pd->setObjectName("pd");
    pd1->setObjectName("pd1");
    //设置父对象
    pd->setParent(&mc);
    pd1->setParent(&mc);
    mb.setParent(&ma); //当用鼠标按下按钮 AAA 时,输出 pd=Bk 和Dk。 因为按钮 AAA 安装的过滤器对象为 mb,
                       //因此由 mb 的 eventFilter 函数处理该事件,输出 pd=BK


    //注册过滤器对象
    
    //此时 mb::eventFilter()返回 0,表示此事件需作进一步处理,
    //于是把该事件传递给目标对象处理(即 pd 所指向的对象),
    // 注意:本例虽然为 mb 设置了父对象 ma,但事件并不会传递给父对象处理,而是返回给目标对象
    //此时调用 D::mousePressEvent 函数,输出 Dk,至此事件处理结束
    pd->installEventFilter(&mb);   

    pd1->installEventFilter(&ma);
    mc.resize(333,222);
    mc.show();
    a.exec();
    return 0;
}


②、 若同一对象安装了多个事件过滤器,则最后安装的过滤器首先被激活。

多个对象过滤器demo:


#include <QApplication>
#include<QWidget>
#include<QMouseEvent>
#include<QPushButton>
#include<QObject>
#include <iostream>
using namespace std;
class A:public QObject{public:
                       bool eventFilter(QObject *w, QEvent *e)
                       {
                           if(e->type()==QEvent::MouseButtonPress)
                           {
                               cout<<"A"<<endl;
                               return 0;
                           }//此处应返回 0,注意,返回 1 事件将停止传递。
                           return 0;
                       }
                      };


class B:public QObject{public:
                       bool eventFilter(QObject *w, QEvent *e)
                       {
                           if(e->type()==QEvent::MouseButtonPress)
                           {
                               cout<<"B"<<endl;return 0;
                           }
                           return 0;
                       }
                      };

class C:public QObject{public:
                       bool eventFilter(QObject *w, QEvent *e)
                       {
                           static int i=0;
                           if(e->type()==QEvent::MouseButtonPress)
                           {
                               cout<<"C="<<i++<<endl;return 0;
                           }
                           return 0;
                       }
                      };
int main(int argc, char *argv[])
{
    QApplication a(argc,argv); //在 Qt 中 QApplication 类型的对象只能有一个
    //创建对象
    A ma; B mb; C mc,mc1; //事件过滤器对象
    QWidget w; QPushButton *pb=new QPushButton();
    pb->setText("AAA"); pb->move(220,22);
    pb->setParent(&w);//设置父对象
    //注册过滤器对象
    pb->installEventFilter(&ma); pb->installEventFilter(&mb);
    pb->installEventFilter(&mc); pb->installEventFilter(&mc1);
    w.resize(333,222);
    w.show();
    a.exec();
    return 0;
}

4、 为什么使用事件过滤器:

①使用事件过滤器可以简化程序代码。比如按钮 1 和标签 1,对按
下 A 键的事件响应相同的操作,若不使用事件过滤器, 则需要分别子类化按钮和标签部
件,并重新实现各自的事件处理函数。 再如使用同一个子类化按钮的类 C 创建的按钮 1
和按钮 2,对按下键 A, 按钮 1 和按钮 2 需要作不同的响应,若不使用事件过滤器,则他
们的响应是相同的,若使用事件过滤器,则可以拦截按钮1或按钮2的事件并作特殊处理。

②Qt开发中,有些组件的事件往往没有,比如QMenu并没有click事件,那么我们便可以通过事件过滤,来给QMenu处理click事件,包括QLabel,QLineEdit等等

class MainWindow : public QMainWindow
 {
 public:
     MainWindow();
 
 protected:
     bool eventFilter(QObject *obj, QEvent *ev);
 
 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<QKeyEvent*>(event);
             qDebug() << "Ate key press" << keyEvent->key();
             return true;
         } else {
             return false;
         }
     } else {
         // pass the event on to the parent class
         return QMainWindow::eventFilter(obj, event);
     }
 }

5、理解事件过滤器

观察者模式:其原理为,设有一目标对象 S,它有多个观察该对象的对象 G1, G2, G3,
当 S 发生变化时, S 的观察者会依情形改变自身。应用于 Qt 事件过滤器,则是,首先使
用 S 的成员函数 installEventFilter 函数把 G1, G2, G3 设置为 S 的观察者,所有本应传递
给 S 的事件 E,则先传递给观察者 G1, G2, G3, 然后观察者调用其成员函数 eventFilter
对传递进来的事件进行处理,若 eventFilter 返回 true 表示事件处理完毕,返回 false 则返
回给被观察者 S 进行处理。 见下图。

最后

以上就是瘦瘦狗为你收集整理的Qt事件过滤器的全部内容,希望文章能够帮你解决Qt事件过滤器所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(43)

评论列表共有 0 条评论

立即
投稿
返回
顶部