答疑解惑1:qml多个mousearea或button重叠,响应异常的解决办法

qml中,经常会遇到多个需要点击的组件重叠,点击重叠部分时,结果不符预期的问题。因为某个组件设置anchors.fill;parent,或者其他原因,不该触发的组件被触发,该触发的没反应。

作为qml的初学者,可能会很疑惑,调试半天,搞不明白哪里错了。也不知道在怎么设置,才能保证全部的需要点击的组件都可以正常运行。

我查了很多资料,只是谈mousearea用法,很少有人谈到这个问题。所以,我来简单说一下,避免更多新人像我一样踩坑。

预备知识

首先,了解什么叫做渲染。

已知一段qml代码,如下:

import QtQuick 2.15
import QtQuick.Window 2.15

Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("渲染一个带有颜色的矩形")

    Rectangle{
        id:rectangle1
        color: "lightblue"
        anchors.fill: parent
    }
}

运行代码,看到一个蓝色的矩形铺满整个窗口。

可知,渲染就是程序将代码指令变为屏幕上可显示图像的过程

我们已经渲染了一个ranctangle1,然后,再此基础上再渲染一个矩形rectangle2

import QtQuick 2.15
import QtQuick.Window 2.15

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

    Rectangle{
        id:rectangle1
        color: "lightblue"
        anchors.fill: parent
    }

    Rectangle{
        id:rectangle2
        color: "pink"
        width: 100
        height: 100
    }
}

运行程序,查看效果。

重点来了,仔细看

我要交换两个rectangle代码顺序,代码如下:

import QtQuick 2.15
import QtQuick.Window 2.15

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

    Rectangle{
        id:rectangle2
        color: "pink"
        width: 100
        height: 100
    }

    Rectangle{
        id:rectangle1
        color: "lightblue"
        anchors.fill: parent
    }
}

运行上述代码,查看效果。

很奇怪,两个重叠的rectangle,居然会因为定义的代码顺序不一样,渲染输出的结果不一样。

所以,问题的解决方法已经呼之欲出,关键就是代码顺序,mousearea或者qml其他组件是一样的道理。下面的内容可以不看。。。。

知识点:qml组件层级及其渲染顺序

qml的可视组件有xyz属性,xy决定组件的在屏幕的渲染位置

z轴垂直于屏幕,决定组件的渲染先后顺序,我称其为渲染层级

其值取值范围可以是正数负数,默认所有的组件z的值都是0,z值相同代表组件处同一个层级

不同层级间,将会按照z值,从小到大依次渲染

因此,手动设置z值,可以避免代码定义顺序的影响,调整组件在z轴上的位置

z值更小者处于更底层位置,z值最大者会处于渲染结果的最表面。

同一个层级下,遵循组件定义顺序为qml的渲染顺序,这一默认规则

此时,先定义的先被渲染,后被渲染的将处于窗口的表层

形象理解,渲染就像向桌子上贴贴纸,后来者会盖住前者。把所有贴纸贴到桌子上后,就是最终的渲染结果。最后贴的贴纸会处于桌面的表面,如果外层的贴纸大小大于内层贴纸,就会完全覆盖掉内层。就会导致看不到内层的贴纸图案。要想看到就得先撕下最外层。

解决方法

mousearea和button,还有许多qml组件,遵循以上运行规则。

因此,有多个重叠的可点击组件,想要正常被触发,就不能让大面积的组件完全叠在小面积组件上,否则点击小面积组件,响应的是大面积组件

所以解决方法很简单,就是调整渲染的先后顺序:

1.调整组件的定义顺序,先定义大面积组件,避免小面积组件后被覆盖掉

2.调整mousearea或button等多个组件的z值,让小面积组件裸露在重叠区域表层

两种方法根据情况和需求,选择使用即可

额外补充说明

这个方法,只能让点击位置最表面的那一个组件响应,内层不会响应

如果希望点击区域重叠的组件,被点击时都能响应。

就需要传递表层鼠标事件到内层,如果有多层重叠,需要一层一层传递鼠标事件才能保证全部响应

常用的设置方法我来简单介绍一下

把mousearea的属性propagateComposedEvents=true

并设置mouse.accepted=false,表示鼠标事件可以继续向内传递到下一层

示例代码如下:
 

Rectangle {
    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;
        }
      }
   }
}

原来未设置时,blue在最顶层,所以点击重叠部分只能输出clicked blue,

在blue中添加设置后,点击重叠区域,log就能输出 clicked blue,clicked yellow了

此时,如果将yellow设置z值设为1,blue的z值不变,点击重叠区域

则log又只能输出clicked yellow

这时向yellow添加设置,传递yellow的鼠标事件,log会再次输出两者: clicked yellow,clicked blue

  • 7
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值