无法单击 MouseArea 下面的按钮

Can't click button below a MouseArea

这里我有一个矩形,它是父矩形和子矩形。子矩形有一个 MouseArea 允许您滑动子矩形。现在,我想在父矩形上有一个按钮(在子矩形和 MouseArea 下方),即使子矩形覆盖了按钮,我也想单击该按钮。这是一个例子

import QtQuick 2.15
import QtQuick.Window 2.0
import QtQuick.Controls 2.15

Window {
  visible: true
  width: 800
  height: 800

  Rectangle {
      id: root
      anchors.fill: parent
      color: "yellow"

      Button {
          id: button1
          x: 314
          y: 182
          text: qsTr("Button")
          onClicked: console.log("Hello")
      }

      Rectangle {
          id: panel
          width: parent.width
          height: parent.height * 0.8
          radius: 20
          color: "orange"
          opacity: 0.2
          MouseArea {
              id: mouseArea
              anchors.fill: parent
              drag.target: panel
              drag.minimumY: 0
              drag.maximumY: 0
              drag.minimumX: -panel.width
              drag.maximumX: 0
              onReleased: {
                  //if the panel is swiped more than 30% it will hide
                  //else it will go back to the original position
                  //this makes a pretty nice effect :)
                  if (panel.x < -panel.width * 0.3) {
                      //we need to make sure that a state change happens to
                      //fire the transition animation
                      root.state = "show"
                      root.state = "hide"
                  }
                  else {
                      root.state = "hide"
                      root.state = "show"
                  }
              }
          }
      }

      Rectangle {
          id: button
          width: 45
          height: width
          radius: 5
          color: "lightblue"
          anchors.bottom: parent.bottom
          anchors.left: parent.left
          MouseArea {
              anchors.fill: parent
              onClicked: {
                  root.state = root.state === "show" ? "hide" : "show"
              }
          }
      }

      state: "show"
      states: [
          State {
              name: "hide"
              PropertyChanges { target: panel; x: -panel.width }
          },
          State {
              name: "show"
              PropertyChanges { target: panel; x: 0 }
          }
      ]

      transitions: Transition {
          NumberAnimation {
              target: panel
              property: "x"
              duration: 1000
              easing.type: Easing.OutCubic
          }
      }
  }
}

如何在不滑动子矩形的情况下单击按钮?

最简单的解决方案是将 button1 放在面板下方。像这样

Rectangle {
      id: panel
      width: parent.width
      height: parent.height * 0.8
      radius: 20
      color: "orange"
      opacity: 0.2
      MouseArea {
          id: mouseArea
          anchors.fill: parent
          drag.target: panel
          drag.minimumY: 0
          drag.maximumY: 0
          drag.minimumX: -panel.width
          drag.maximumX: 0
          onReleased: {
              //if the panel is swiped more than 30% it will hide
              //else it will go back to the original position
              //this makes a pretty nice effect :)
              if (panel.x < -panel.width * 0.3) {
                  //we need to make sure that a state change happens to
                  //fire the transition animation
                  root.state = "show"
                  root.state = "hide"
              }
              else {
                  root.state = "hide"
                  root.state = "show"
              }
          }
      }
  }
  Button {
      id: button1
      x: 314
      y: 182
      text: qsTr("Button")
      onClicked: console.log("Hello")
  }

首先你需要在mouseArea中检测拖动是否处于活动状态,如果拖动未处于活动状态则检测触发鼠标按下事件的点是否也在按钮 1 面板 下方。您可以使用 ItemmapToItem 方法来做到这一点。如果是这种情况,那么您可以手动设置 button1 pressed 可视化。

然后当 released 事件被触发时,你会检测你是否仍在 button1 内并发出特殊信号,例如buttonBelowClicked。该信号需要通过信号链连接到 button1 clicked 信号。

请注意,您需要始终在 mouseArea onReleased 中重置 button1 按下的可视化,因为您可能已经开始 panelbutton1 的顶部拖动并且按钮显示按下的可视化但是然后拖动被启用...

Window {
    visible: true
    width: 800
    height: 800

    Rectangle {
        id: root
        anchors.fill: parent
        color: "yellow"

        Button {
            id: button1
            x: 314
            y: 182
            text: qsTr("Button")
            onClicked: console.log("Hello")
            Component.onCompleted: mouseArea.buttonBelowClicked.connect(clicked)
        }

        Rectangle {
            id: panel
            width: parent.width
            height: parent.height * 0.8
            radius: 20
            color: "orange"
            opacity: 0.2
            MouseArea {
                id: mouseArea
                signal buttonBelowClicked
                anchors.fill: parent
                drag.target: panel
                drag.minimumY: 0
                drag.maximumY: 0
                drag.minimumX: -panel.width
                drag.maximumX: 0
                onPressed: {
                    if (!drag.active) {
                        if (isPointInsideButton1(mouse.x, mouse.y)) {
                            button1.down = true
                        }
                    }
                }
                onReleased: {
                    if (!drag.active) {
                        if (isPointInsideButton1(mouse.x, mouse.y)) {
                            buttonBelowClicked()
                        }
                    } else {
                        if (panel.x < -panel.width * 0.3) {
                            root.state = "show"
                            root.state = "hide"
                        }
                        else {
                            root.state = "hide"
                            root.state = "show"
                        }
                    }
                    button1.down = undefined
                }

                function isPointInsideButton1(x, y) {
                    const mapped = panel.mapToItem(button1, x, y)
                    if (button1.contains(Qt.point(mapped.x, mapped.y))) {
                        return true
                    }
                    return false
                }
            }
        }

        Rectangle {
            id: button
            width: 45
            height: width
            radius: 5
            color: "lightblue"
            anchors.bottom: parent.bottom
            anchors.left: parent.left
            MouseArea {
                anchors.fill: parent
                onClicked: {
                    root.state = root.state === "show" ? "hide" : "show"
                }
            }
        }

        state: "show"
        states: [
            State {
                name: "hide"
                PropertyChanges { target: panel; x: -panel.width }
            },
            State {
                name: "show"
                PropertyChanges { target: panel; x: 0 }
            }
        ]

        transitions: Transition {
            NumberAnimation {
                target: panel
                property: "x"
                duration: 1000
                easing.type: Easing.OutCubic
            }
        }
    }
}