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

最终效果

相关推荐
liwenzhuola44 分钟前
解决 Ubuntu 上 Qt Creator 项目编译失败的问题
数据库·qt·ubuntu
娇娇yyyyyy1 小时前
QT编程(18): Qt QItemSelectionModel介绍
开发语言·qt
sthnyph2 小时前
QT开发:事件循环与处理机制的概念和流程概括性总结
开发语言·qt
机器视觉知识推荐、就业指导6 小时前
LVGL真能动摇Qt的地位吗?
开发语言·qt·系统架构
羊小猪~~11 小时前
【QT】--QWIdget与QDialog
开发语言·数据库·c++·后端·qt·求职招聘
Blasit12 小时前
Qt 程序打包,运行提示找不到或无法加载平台插件 qwindows.dll
开发语言·windows·qt
C++ 老炮儿的技术栈12 小时前
c++常见配置文件格式 JSON、INI、XML、YAML 它们如何解析
xml·开发语言·c++·windows·qt·json
镜中月ss12 小时前
QT中的资源树
开发语言·qt·qml
Laurence12 小时前
GitHub 1.2 万星 Qt 项目 VNote 源码解读(一):核心类与主流程
qt·github·源码·代码·介绍·解读·vnote
Hello.Reader1 天前
从零开始安装 Qt完整新手教程(1)
开发语言·qt