一个Qt鼠标透传场景与事件过滤器的用法

一个Qt鼠标透传场景与事件过滤器的用法

最近工作中遇到一个开发场景,将一个QWidget控件(称为控件A)放入QScrollArea,该控件A重写了QWidget::wheelEvent,根据鼠标滚轮事件缩放内部的绘制视图。当控件过大时,QScrollArea的滚动条出现,此时鼠标滚动也会触发页面滚动,用一个Demo演示:

问题

对于这个体验问题,提出了一个方案,当按住Ctrl并滚动滚轮,执行控件A的触发缩放逻辑;当没有按Ctrl时,仅滚动页面。但是,由于该控件A是第三方库创建的,无法重写事件处理,所以只能借助Qt事件过滤器或者其他方案。

分析

出现该问题的原因是,控件A重写QWidget::wheelEvent处理缩放,没有将QWheelEvent设置为accepted,即标记为已处理,而Qt对于输入事件(鼠标、键盘等),如果目标控件没有处理,则会将事件投递给其父控件。

因此需要通过事件过滤器,处理控件A的逻辑,不继续透传事件,或者直接透传事件。

基本事件分发流程

Qt分发事件的总入口在QApplication::notify,事件在这里被分发给目标控件。事件分发后,对于Qt的鼠标等事件,会根据事件是否被处理(即QEvent::isAccepted),将未处理的事件透传给当前控件的父控件,或者称之为冒泡。直到其中一个父级控件处理,事件停止透传。

事件分发给目标控件前,会查找目标控件安装的事件过滤器(通过QObject::installEventFilter注册)对象,并按顺序调用其QObject::eventFilter。该方法返回bool值,true则直接返回到QApplication::notify,后续的事件过滤器对象也就不再被调用。

如果所有的事件过滤器对象(QObject::eventFilter)都返回false,则会调用目标控件的QObject::event 。对于QWidget,此时会根据事件类型,调用对应的事件处理函数(如 QWidget::wheelEvent)。不同的Qt控件,可能也会重写QWidget::event,在调用其事件处理函数前,执行一些逻辑。

解决方法

首先控件A安装事件过滤器到任意QObject对象,重写该对象的eventFilter方法:

cpp 复制代码
bool Widget::eventFilter(QObject *watched, QEvent *event)
{
    if(event->type() == QEvent::Wheel && watched == target)
    {
        if(static_cast<QWheelEvent*>(event)->modifiers() & Qt::CTRL)
        {
            watched->event(event); 	// 1
            event->accept();		// 2
            return true;			// 3
        }
        else
        {
            event->ignore();		// 4
            return true;			// 5
        }
    }
    return false;	// 原则上应该调用父类的eventFilter。如果父类没有被安装过滤器,直接false即可
}

代码解释:

  • 1,直接调用QObject::event接口。因为QWidget::event重写时改成protected
  • 2、3,标记事件已被处理,并返回true。按上面说的事件分发流程,回到QApplication::notify,由于事件被处理,鼠标滚轮事件不再继续透传给父控件,分发中断。
  • 4、5,标记事件未处理,返回true,同样回到QApplication::notify,事件透传给父控件。因此跳过了当前控件的处理逻辑。

最终效果

相关推荐
海涛高软35 分钟前
QT配置文件详解
开发语言·qt
龙虎榜小红牛系统3 小时前
Wordcloud+PyQt5写个词云图生成器1.0
python·qt·wordcloud
我真的太难了啊7 小时前
QT6学习第五天 第一个QT Quick程序
qt
机器视觉知识推荐、就业指导12 小时前
基于Qt实现的自定义树结构容器:设计与应用
开发语言·qt
进击ing小白14 小时前
QChart数据可视化
qt·信息可视化
斯凯利.瑞恩1 天前
RabbitMQ代码实战2
qt·rabbitmq·ruby
Zafir20241 天前
Qt实现窗口内的控件自适应窗口大小
c++·qt·ui
人才程序员1 天前
详解Qt 中使用虚拟键盘(软键盘qtvirtualkeyboard)
开发语言·数据库·c++·qt·计算机外设·界面·c语音
喵呜角角1 天前
QML TableView 实例演示 + 可能遇到的一些问题(Qt_6_5_3)
开发语言·windows·qt·qml·qt quick
SSONICX1 天前
QT:生成二维码 QRCode
开发语言·qt