Qml 中的那些坑(四)---MouseArea 的 Click / Hover 事件穿透

【写在前面】

我们在 Qml 中经常会遇到这样的情况:

有某个 Item ( 这里称为 Parent ),需要它在鼠标 Enter 时显示,鼠标 Exit 时隐藏。

这时候我们会用一个 MouseArea,然后处理 onEntered / onExited

但是,有一个巨大的坑:

如果这个 Item 里嵌入了其他 Item ( 这里称为 Child ) 并且处理自己的 MouseArea,则会导致 Parent Item 的 MouseArea 失效 ( 即不能接收到相应的事件 )。

本篇主要内容:

  1. MouseArea 的 Click / Press / Release 事件穿透一般方法;

  2. MouseArea 的 Hover 事件穿透以及所有鼠标事件穿透的终极解决方法;


【正文开始】

对于 Click / Press / Release 事件,MouseArea 提供了一个属性:

propagateComposedEvents:bool

此属性保存组合的鼠标事件是否将自动传播到与此 MouseArea 重叠但在视觉堆叠顺序中较低的其他 MouseArea。

默认情况下,此属性为 false。

MouseArea 包含几个组成的事件:clickeddoubleClickedpressAndHold

它们由基本的鼠标事件(如按下)组成,并且与基本事件相比可以以不同的方式传播。

如果 propertyComposedEvents 设置为 true,则组合事件将自动传播到场景中相同位置的其他 MouseAreas。

每个事件将按照堆栈顺序传播到其下方的下一个启用的 MouseArea,并向下传播此可视层次结构,直到 MouseArea 接受该事件为止。

与按下的事件不同,如果没有处理程序,则组合的事件将不会自动被接受。

具体的使用方法相当简单:

  1. Child Item 的 MouseArea 设置 propertyComposedEvents 为 true。

  2. 在相应的事件处理中将 mouse.accepted = false 即可,例如传递 Click 事件:

javascript 复制代码
Rectangle {
    color: "yellow"
    width: 100
    height: 100

    MouseArea {
        anchors.fill: parent
        onClicked: console.log("clicked yellow");
    }

    Rectangle {
        color: "blue"
        width: 50
        height: 50

        MouseArea {
            anchors.fill: parent
            propagateComposedEvents: true
            onClicked: {
                console.log("clicked blue");
                mouse.accepted = false;
            }
        }
    }
}

然而,坑爹的是,对于 onEnteronExit,它们没有 mouse 参数 ( 即不能设置 mouse.accepted = false; ),无法使用此方法传递。

好在我找到了一种不太常见的方式,但相当简单和实用:

Child Item 直接放入 Parent Item 的 MouseArea 中,类似于这样:

javascript 复制代码
Rectangle {
    color: "yellow"
    width: 100
    height: 100

    MouseArea {
        anchors.fill: parent
        onEntered: {}
        onExited: {}

        Rectangle {
            color: "blue"
            width: 50
            height: 50

            MouseArea {
                anchors.fill: parent
                onEntered: {}
                onExited: {}
            }
        }
    }
}

来看看实际效果:

可以看到,上面的小方块没有放在 MouseArea 中,这样导致 Enter / Exit 小方块时会触发紫色大方块的 Exit / Enter 事件。

而下面则放在 MouseArea 中,表现出了正常的 Hover 效果。

然而,奇葩的是这个方法只能穿透( 传递 ) Hover 事件。

那么,如果想要实现 Click / Press / Release / Hover 事件的穿透,只能混用上面的两种方法:

javascript 复制代码
Rectangle {
    color: "yellow"
    width: 100
    height: 100

    MouseArea {
        anchors.fill: parent
        onEntered: {}
        onExited: {}

        Rectangle {
            color: "blue"
            width: 50
            height: 50

            MouseArea {
                anchors.fill: parent
                propagateComposedEvents: true
                onPressed: mouse.accepted = false;
                onReleased: mouse.accepted = false;
                onClicked: mouse.accepted = false;
                onEntered: {}
                onExited: {}
            }
        }
    }
}

这就是终极解决方案 ( 灰常简单有没有Ծ‸ Ծ )。


【结语】

最后,动图的代码比较长,就贴个链接了(多多star呀..⭐_⭐):

CSDN的:MouseArea的Click/Hover事件穿透-C++文档类资源-CSDN下载

Github的:github.com/mengps/QmlE...

相关推荐
喉咙痛的恐龙13 分钟前
C++之内存管理
java·jvm·c++
心怀花木14 分钟前
【C++】哈希
数据结构·c++·算法·哈希算法·散列表
小王同学的C++19 分钟前
什么是 C++ 内联函数?它的作用是什么?
开发语言·c++
Lenyiin20 分钟前
03.01、三合一
数据结构·c++·leetcode
cccccc语言我来了1 小时前
c++--------《set 和 map》
开发语言·c++·windows
程序猿阿伟2 小时前
《原子操作:程序世界里的“最小魔法单位”解析》
java·数据库·c++
一丝晨光2 小时前
Chrome和Chromium的区别?浏览器引擎都用的哪些?浏览器引擎的作用?
前端·c++·chrome·webkit·chromium·blink·trident
凤枭香2 小时前
数字图像处理(c++ opencv):图像复原与重建-常见的滤波方法--统计排序滤波器
c++·图像处理·opencv·计算机视觉
凤枭香2 小时前
数字图像处理(c++ opencv):图像复原与重建-常见的滤波方法--自适应滤波器
开发语言·c++·图像处理·opencv
埋头编程~3 小时前
【C++】踏上C++学习之旅(八):深入“类和对象“世界,掌握编程的黄金法则(三)(内含运算符重载和拷贝构造函数)
java·c++·学习