Qml 中的那些坑(五)---MouseArea 上的 ListView 滚轮事件穿透

【写在前面】

最近在 Qml 中使用 MouseArea 时发现了一个奇怪的现象:

位于 MouseArea 上的 ListView 在处理了滚轮事件的情况下进行滚轮,下面的 MouseArea 却在某些情况下接收到了这个事件。

按照直觉,ListView 明明有内部的滚轮事件处理,应该阻止事件向下传递才对,然而此时的情况却出乎意料,因此在此记录并附上解决方案。


【正文开始】

首先,我们来看一个很简单的例子:

javascript 复制代码
import QtQuick 2.15
import QtQuick.Window 2.15

Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")

    Rectangle {
        id: scaledRect
        width: 100
        height: 100
        anchors.centerIn: parent
        color: "red"
    }

    MouseArea {
        id: mouseArea1
        anchors.fill: parent
        onWheel: (wheel) => {
             if (wheel.angleDelta.y > 0) scaledRect.scale += 0.1;
             else if (wheel.angleDelta.y < 0) scaledRect.scale -= 0.1;
             print("mouseArea1 wheel event!");
         }
    }

    ListView {
        id: listView
        width: parent.width * 0.5
        height: parent.height * 0.5
        anchors.centerIn: parent
        clip: true
        model: 100
        spacing: 5
        delegate: Rectangle {
            width: listView.width
            height: 20
            color: "#8000ff00"

            Text {
                anchors.centerIn: parent
                text: index
            }
        }
    }
}

按道理,我在最顶层的ListView 上滚动鼠标,应当不会影响到下面的的红色方块,然而,事实并非如此:

可以看到,某些时候我在 ListView 上滑动滚轮,底层的 MouseArea 也会接收并处理滚轮事件。

一开始,我以为是 ListView 的 spaing 属性( 代理项的间隔 )导致滚轮事件穿透,然而去掉后并没有卵用,问题仍然没有解决。

不管怎样,这是一个相当坑爹的 BUG( 也许不是,但至少影响到我了 ),那么必须要处理好它。

这里我用了一点奇怪的写法,但相当有用,方法是增加一个 MouseArea 并处理其滚轮事件( 自己处理总不会穿透了吧!):

javascript 复制代码
    MouseArea {
        width: parent.width * 0.5
        height: parent.height * 0.5
        anchors.centerIn: parent
        onWheel: (wheel) => wheel.accepted = true;

        ListView {
            id: listView
            anchors.fill: parent
            clip: true
            model: 100
            spacing: 5
            delegate: Rectangle {
                width: listView.width
                height: 20
                color: "#8000ff00"

                Text {
                    anchors.centerIn: parent
                    text: index
                }
            }
        }
    }

没错,将 ListView 置于一个 MouseArea 内 即可解决问题。


【结语】

最后,我发现 Qt6 仍有这种情况,因此需要大家格外注意。

相关推荐
硅农深芯4 小时前
如何使用ptqt5实现进度条的动态显示
开发语言·python·qt
Lhan.zzZ4 小时前
Qt数据可视化实战:饼图、线图与表格的完整指南
开发语言·qt·信息可视化
feiyangqingyun5 小时前
Qt/C++编写GB28181服务/前后端分离/定义一套交互协议/视频点播/录像回放和控制/警情通知
c++·qt·交互
虾米Life6 小时前
基于微服务脚手架的视频点播系统 (仿B站) [客户端] -1
c++·qt·微服务·架构
yugi9878388 小时前
基于Qt框架开发多功能视频播放器
开发语言·qt
MeowKnight95816 小时前
【Qt】Qt实践记录2——TCP通信服务器和客户端demo
笔记·qt
Larry_Yanan1 天前
QML学习笔记(五十二)QML与C++交互:数据转换——时间和日期
开发语言·c++·笔记·qt·学习·ui·交互
十启树1 天前
Qt 中实现炫酷的开机启动动画
qt
一叶之秋14122 天前
QT背景介绍与环境搭建
开发语言·qt
QT 小鲜肉2 天前
【QT/C++】Qt网络编程进阶:UDP通信和HTTP请求的基本原理和实际应用(超详细)
c语言·网络·c++·笔记·qt·http·udp