最近在写弹出层时遇到事件穿透,刚好找到这篇文章得以解决,在这分享一下。核心思路:一个mask层,一个最顶层,都用rectangle,禁止事件穿透。

Rectangle {
    id: root
    width: 100
    height: 200
    color: 'lightblue'
    z:100
    transformOrigin: Item.Center  // 无效
    // 公有属性
    property bool showMask : false;
    property string animationType : 'none';
    property int duration : 500
    property int easingType : Easing.OutBounce
    // 私有属性
    property int innerX;
    property int innerY;
    property int innerWidth;
    property int innerHeight;
    property double innerOpacity;
    //------------------------------
    // 事件
    //------------------------------
    // 属性备份一下,避免动画对属性进行变更
    Component.onCompleted: {
        save();
    }
    function show()
    {
        reset();
        switch (animationType)
        {
            case "fade":     animFadeIn.start(); break;
            case "focus":    animFocusIn.start(); break;
            case "width":    animWidthIncrease.start(); break;
            case "height":   animHeightIncrease.start(); break;
            case "size":     animBig.start(); break;
            case "flyDown":  animInDown.start(); break;
            case "flyUp":    animInUp.start(); break;
            case "flyLeft":  animInLeft.start(); break;
            case "flyRight": animInRight.start(); break;
            default:         this.visible = true;
        }
    }
    function hide()
    {
        switch (animationType)
        {
            case "fade":    connector.target = animFadeOut;        animFadeOut.start(); break;
            case "focus":   connector.target = animFocusOut;       animFocusOut.start(); break;
            case "width":   connector.target = animWidthDecrease;  animWidthDecrease.start();   break;
            case "height":  connector.target = animHeightDecrease; animHeightDecrease.start();  break;
            case "size":    connector.target = animSmall;          animSmall.start();   break;
            case "flyDown": connector.target = animOutUp;          animOutUp.start();   break;
            case "flyUp":   connector.target = animOutDown;        animOutDown.start(); break;
            case "flyLeft": connector.target = animOutRight;       animOutRight.start();break;
            case "flyRight":connector.target = animOutLeft;        animOutLeft.start(); break;
            default:        close();
        }
    }
    // 动画结束后调用的脚本
    Connections{
        id: connector
        target: animInDown
        onStopped: close()
    }
    //------------------------------
    // 辅助方法
    //------------------------------
    function getRoot(item)
    {
        return (item.parent !== null) ? getRoot(item.parent) : item;
    }
    function save()
    {
        innerX = root.x;
        innerY = root.y;
        innerWidth = root.width;
        innerHeight = root.height;
        innerOpacity = root.opacity;
        console.log("x=" + innerX + " y="+innerY + " w=" + innerWidth + " h="+innerHeight);
    }
    function reset()
    {
        root.x = innerX;
        root.y = innerY;
        root.width = innerWidth
        root.height = innerHeight;
        root.opacity = innerOpacity;
        root.scale = 1;
        connector.target = null;
        mask.visible = showMask;
        root.visible = true;
    }
    // 立即关闭
    function close()
    {
        mask.visible = false;
        root.visible = false;
        log();
    }
    function log()
    {
        console.log("x=" + x + " y="+y + " w=" + width + " h="+height);
    }
    //------------------------------
    // 遮罩
    //------------------------------
    // 禁止事件穿透
    MouseArea{
        anchors.fill: parent;
        onPressed:{
             mouse.accepted = true
        }
        drag.target: root  // root可拖动
    }
    // 灯箱遮罩层
    Mask{
        id: mask
        visible: false
    }
    //------------------------------
    // 动画
    //------------------------------
    // fadeIn/fadeOut
    PropertyAnimation {
        id:animFadeIn
        target: root
        duration: root.duration
        easing.type: root.easingType
        property: 'opacity';
        from: 0;
        to: root.innerOpacity
    }
    PropertyAnimation {
        id: animFadeOut
        target: root
        duration: root.duration
        easing.type: root.easingType
        property: 'opacity';
        from: root.innerOpacity;
        to: 0
    }
    ...
}

效果图:

阅读原文