一个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,事件透传给父控件。因此跳过了当前控件的处理逻辑。

最终效果

相关推荐
QT 小鲜肉3 小时前
【个人成长笔记】Qt 中 SkipEmptyParts 编译错误解决方案及版本兼容性指南
数据库·c++·笔记·qt·学习·学习方法
OneSea3 小时前
Debian编译Qt5
linux·qt
看到我,请让我去学习3 小时前
Qt 控件 QSS 样式大全(通用属性篇)
开发语言·c++·qt
曦樂~9 小时前
【Qt】信号与槽(Signal and Slot)- 简易计算器
开发语言·数据库·qt
十五年专注C++开发9 小时前
QDarkStyleSheet: 一个Qt应用的暗色主题解决方案
开发语言·c++·qt·qss
Algebraaaaa1 天前
什么是前端、后端与全栈开发,Qt属于什么?
开发语言·前端·qt
大美B端工场-B端系统美颜师1 天前
工控软件开发选择难?Electron、Qt、WPF 对比
qt·electron·wpf
QT 小鲜肉1 天前
【个人成长笔记】Qt Creator快捷键终极指南:从入门到精通
开发语言·c++·笔记·qt·学习·学习方法
feiyangqingyun1 天前
Qt项目作品在苹果macos上编译运行效果/视频监控系统/物联网平台等
开发语言·qt·macos
fsnine1 天前
Python图形化界面——pyqt5教程
开发语言·python·qt