zoukankan      html  css  js  c++  java
  • QT中事件处理器和事件过滤器实现实例

    Qt中事件处理的方式,最常用的就是使用事件处理器(event handler)和事件过滤器(event filter)这两种方法。接下来,我们就来看看事件处理器和事件过滤器是怎么使用的。

    事件处理器

    Qt中针对每一种常见的事件类型都提供了相应的事件处理器,我们如果想捕获某种类型的事件并进行自定义处理,那么只需要实现重写这些事件处理器就行。常见的事件类型和对应的事件处理器如下图所示:

    用户自定义事件定义如下:

    在日常使用中,我们最常使用的鼠标事件:

    新建一个基于QWidget的应用程序,在QWidget的头文件中找到鼠标操作事件处理器虚函数如下:

    我们将其在我们的QWidget子类中重写实现:

     

    到这里这个功能就实现了,大家看看上面的头文件就知道这里还实现了其它类型事件的处理,其实都是一样的思路,找到欲处理的事件类型,找到对应的事件处理器,重写事件处理器中处理事件的方法即可。这个看起来比较简单!

     

     

    事件过滤器

    Qt事件模型中一项非常强大的功能就是一个QObject实例可以监视另一个QObject实例中的事件,实现方法是在目标对象中安装事件过滤器。

    假设我们有一个Dialog控件,由一些QLineEdit控件组成。我们希望使用Space键得到下一个QLineEdit的输入焦点。

    一个最直接的方法是继承QLineEdit重写keyPressEvent()函数,当点击了Space键时,调用focusNextChild():

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    void MyLineEdit::keyPressEvent(QKeyEvent *event)
    {
        
    if (event->key() == Qt::Key_Space)
        {
            focusNextChild();
        }
        
    else
        {
            QLineEdit::keyPressEvent(event);
        }
    }

    这个方法有一个最大的缺点:如果我们在窗体中使用了很多不同类型的控件(QComboBox,QSpinBox等等),我们也要继承这些控件,重写它们的keyPressEvent()。

    一个更好的解决方法是让Dialog监视其子控件的键盘事件,在监视代码处实现以上功能。

    这就是事件过滤的方法。实现一个事件过滤包括两个步骤:

    1、在目标对象上调用installEventFilter(),注册监视对象。

    2、在监视对象的eventFilter()函数中处理目标对象的事件。

     Dialog.h 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    #include <QDialog>

    class QLineEdit;
    class Dialog : public QDialog
    {
        Q_OBJECT

    public:
        Dialog(QWidget *parent = 
    0);
        ~Dialog();

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

    private:
        QLineEdit*      firstNameEdit ;
        QLineEdit*      lastNameEdit;
        QLineEdit*      cityEdit;
        QLineEdit*      phoneNumberEdit;
    };

    注册监视对象的位置是在CustomerInfoDialog的构造函数中:

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    Dialog::Dialog(QWidget *parent)
        : QDialog(parent)
    {
        QFormLayout* formLayout = new QFormLayout;
        firstNameEdit    = 
    new QLineEdit();
        lastNameEdit     = 
    new QLineEdit();
        cityEdit         = 
    new QLineEdit();
        phoneNumberEdit  = 
    new QLineEdit();
        formLayout->addRow(tr(
    "&FirstName:"), firstNameEdit);
        formLayout->addRow(tr(
    "&LastName:"), lastNameEdit);
        formLayout->addRow(tr(
    "&City:"), cityEdit);
        formLayout->addRow(tr(
    "&PhoneNumber:"), phoneNumberEdit);
        setLayout(formLayout);

        
    // 给QLineEdit安装事件过滤器
        firstNameEdit->installEventFilter(this);
        lastNameEdit->installEventFilter(
    this);
        cityEdit->installEventFilter(
    this);
        phoneNumberEdit->installEventFilter(
    this);
    }

    事件过滤器注册后,发送到firstNameEdit,lastNameEdit,cityEdit,phoneNumberEdit控件的事件首先到达CustomerInfoDialog::eventFilter()函数,然后在到达最终的目的地。

    下面是eventFilter()函数的代码:

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    bool Dialog::eventFilter(QObject *target, QEvent *event)
    {
        
    if (target == firstNameEdit ||
            target == lastNameEdit ||
            target == cityEdit ||
            target == phoneNumberEdit)
        {
            
    if (event->type() == QEvent::KeyPress)
            {
                QKeyEvent *keyEvent = 
    static_cast<QKeyEvent *>(event);
                
    if (keyEvent->key() == Qt::Key_Space)
                {
                    focusNextChild();
                    
    return true;
                }
            }
        }
        
    return QDialog::eventFilter(target, event);
    }

    首先,我们看是目标控件是否为QLineEdit,如果事件为键盘事件,把QEvent转换为QKeyEvent,确定被敲击的键。如果为Space键,调用focusNextChild(),把焦点交给下一个控件,返回true通知Qt已经处理了这个事件,如果返回false,Qt将会把事件传递给目标控件,把一个空格字符插入到QLineEdit中。

     

  • 相关阅读:
    kmeans 聚类
    HTTP与HTTPS相关知识
    如何和统计学家分享数据How to share data with a statistician
    使用 Python 进行 T检验
    Jupyter Lab目录插件安装
    【Python项目】爬取新浪微博个人用户信息页
    【Python项目】爬取新浪微博签到页
    使用SVN服务器管理源码
    [转载]C++命名规则
    C++&OpenCV中读取灰度图像到数组的两种
  • 原文地址:https://www.cnblogs.com/MakeView660/p/10760977.html
Copyright © 2011-2022 走看看