QT EventFilter 事件过滤器实现鼠标追踪

EventFilter的作用域 ?
1. 只针对本 ui界面中的部件?

2. 每个独立的 ui界面,都可以有一个不同作用域限定的:: 相同函数名的、内容相同的 event处理函数?

参考:

https://blog.csdn.net/ken2232/article/details/130272182

某些应用场景下,需要拦截某个组件发生的事件,让这个事件不再向其他组件进行传播,这时候可以为这个组件或其父组件安装一个事件过滤器(evenFilter)

设计思想,要点:拦截 <---> 不再向其他组件进行传播

前言

使用事件过滤器之前需要了解qt事件的运行机制。

这里举一个应用场景来记录事件过滤器的整个使用过程。

实现这样一个功能,在一个窗口上追踪鼠标的的移动位置,如果这个窗口是一个单一的窗口,没有任何子控件,那么只需要开启鼠标追踪,然后重写mouseMoveEvent(),就可以实现功能了。

但是如果有子控件的情况下,鼠标移动到子控件上时,移动事件会优先被子控件处理,那如果要在一个复杂的页面上完成这样的功能,岂不是需要重写所有子控件的鼠标事件?

事件过滤机制

Qt 在提供事件循环服务时,为了QObject提供了

bool eventFilter(QObject* watched, QEvent* event) override;

这个函数会在event()函数被调用之前调用,如果返回值为true,那么表示这个事件被处理了,这个事件将跳过event()函数的处理。

并且QObject还提供了

void QObject::installEventFilter(QObject *filterObj)

这个函数可以将一个QObject作为一个过滤器,安装到另一个QObject对象,那么安装之后,在调用自己本身的eventFilter()之前会先调用过滤器的这个函数。

事件过滤器可以设置多个,在调用时会根据安装的先后顺序调用。

示例

明白了这个机制之后,怎么实现前面的需求也就明了了,只需要创建一个QObject,然后重写eventFilter() 函数,在函数中实现对鼠标的追踪,然后再将这个过滤器安装到所有的子控件中即可。

#pragma once
#include <QWidget>
#include <QVBoxLayout>
#include <QLabel>
#include <QTextEdit>
namespace EFT {

    class widget :public QWidget {
    public:
        widget(QWidget* parent = 0);
        ~widget();

    protected:
        bool eventFilter(QObject* watched, QEvent* event) override;
    private:
        QVBoxLayout* vLaout;
        QLabel* label;
        QTextEdit* textEdit;
    };
}

#include "EventFilterTest.h"
#include <QEvent>
#include <QMouseEvent>
#include <QDebug>
EFT::widget::widget(QWidget* parent /*= 0*/)
    :QWidget(parent)
{
    //初始化窗口布局
    vLaout = new QVBoxLayout();
    label = new QLabel();
    label->setText("This is a label");
    textEdit = new QTextEdit();
    vLaout->addWidget(label);
    vLaout->addWidget(textEdit);
    this->setLayout(vLaout);

    //开启鼠标追踪
    this->setMouseTracking(true);
    label->setMouseTracking(true);
    textEdit->viewport()->setMouseTracking(true);
    //安装过滤器
    label->installEventFilter(this);
    textEdit->viewport()->installEventFilter(this);
    this->installEventFilter(this);
}

EFT::widget::~widget()
{
    textEdit->deleteLater();
    label->deleteLater();
    vLaout->deleteLater();
}


bool EFT::widget::eventFilter(QObject* watched, QEvent* event)
{
    if (event->type() == QEvent::MouseMove)
    {
        auto e = dynamic_cast<QMouseEvent*>(event);
        label->setText(QString("pos x: %1  y: %2").arg(e->globalX()).arg(e->globalY()));
        return true;
    }
    return    QWidget::eventFilter(watched, event);
}

运行结果:

http://cppdebug.com/archives/326

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值