【问题标题】:How to include child mouse hover events in the parent MouseArea using QML?如何使用 QML 在父 MouseArea 中包含子鼠标悬停事件?
【发布时间】:2013-08-10 17:04:04
【问题描述】:

我想在 QML 中实现以下场景。


这是ListView 元素的示例/简化委托:

Component {
    Item {
         id: container
         MouseArea {
         anchors.fill: parent
         hoverEnabled: true

         onClicked: {
             container.ListView.view.currentIndex = index
             container.forceActiveFocus();
         }
         onEntered: {
             actionList.state = "SHOW";
             myItem.state = "HOVER"
         }
         onExited: {
             actionList.state = "HIDE";
             myItem.state = "NORMAL"
         }
         Rectangle {
             id: myItem
             color: "gray"
             anchors.fill: parent
             Row {
                 id: actionList
                 spacing: 5; anchors.fill: parent
                 Image {
                     id: helpAction
                     source: ""    //Some image address
                     width: 16; height: 16; fillMode: Image.PreserveAspectFit
                     states: [
                         State {
                             name: "NORMAL"
                             PropertyChanges { target: helpAction; opacity: 0.7 }
                         },
                         State {
                             name: "HOVER"
                             PropertyChanges { target: helpAction; opacity: 1.0 }
                         }
                     ]
                     MouseArea {
                         hoverEnabled: true
                         anchors.fill: parent

                         onEntered: {
                             parent.state = "HOVER";
                         }
                         onExited: {
                             parent.state = "NORMAL";
                         }
                     }
                     states: [
                         State {
                             name: "SHOW"
                             PropertyChanges { target: actionList; visible: false }
                         },
                         State {
                             name: "HIDE"
                             PropertyChanges { target: actionList; visible: true }
                         }
                     ]
                 }

                 //Other action buttons...

                 states: [
                     // `NORMAL` and `HOVER` states definition here...
                 ]
             }
         }
    }
}

但我对MouseArea 有疑问。
内部MouseArea (actionButton) 对于entered 事件不能正常工作。当鼠标进入动作按钮时,外部MouseArea 触发exited 事件。

我的代码有错误吗?更一般地说,如何在 QML 中实现这样的场景?

【问题讨论】:

    标签: qt qml qt5 qtquick2


    【解决方案1】:

    我尝试了一些方法,但似乎无法同时将鼠标悬停在两个 MouseArea 上。 preventStealingpropagateComposedEvents 似乎仅在您有点击事件时才有效。但是从内部MouseArea 可以触发另一个entered() 信号。像这样的:

    import QtQuick 2.1
    
    Rectangle {
        width: 500
        height: 500
    
        Rectangle {
            width:300
            height: 300
            color: "red"
    
            MouseArea {
                id: big
                anchors.fill: parent
                hoverEnabled:true
                onEntered: {
                    console.log("ENTERED BIG mousearea");
                }
                onExited: {
                    console.log("EXITED BIG mousearea");
                }
            }
    
            Rectangle {
                anchors.centerIn: parent
                height: 100
                width: 100
                color: "green"
    
                MouseArea {
                    anchors.fill: parent
                    hoverEnabled:true
                    onEntered: {
                        console.log("ENTERED small mousearea");
                        big.entered();
                    }
                    onExited: {
                        console.log("EXITED small mousearea");
                        big.exited();
                    }
                }
            }
        }
    }
    

    问题是来自包含MouseAreaexited() 信号将在再次调用entered() 之前被调用。因此,您可能需要“延迟”exited() 中的状态更改,以确保您确实想要隐藏您的操作按钮。另一种解决方案是保存当前鼠标位置并仅在使用鼠标在其边框之一上调用 exited() 时隐藏按钮。

    【讨论】:

    • 不错但不完整。我该如何实施第二个建议?有可能吗?
    • onExited()你可以使用mouseXmouseY来获取当前鼠标位置并猜测你是否在你的大鼠标区域的边界(基于它自己的x,@ 987654337@、heightwidth)。我试过了,但是当你快速移动鼠标时,mouseX 会关闭。仍然是第一步
    • 是的,我尝试了您的建议。但是在快速鼠标退出时,mouseX 不正确(例如 onExited 已触发但鼠标位置为 (14,57))。使用onPositionChanged也是同样的问题。
    • 我将此问题报告给开发团队bugreports.qt-project.org/browse/QTBUG-32909
    • 我进行了更多调查,似乎一旦您移出MouseAreamouseXmouseY 的值就不正确(它写在文档上)。您可以尝试在 C++ 中而不是在 QML 中检索鼠标位置,因为重叠的MouseArea不适用于悬停事件
    【解决方案2】:

    试试这个:

    • 将信号添加到鼠标进入时发出的内部区域。
    • 将信号连接到外部区域。
    • 信号使外部区域进入悬停状态。

    鼠标退出两者仍会取消悬停状态。当您将鼠标从控件上移开时,它应该可以正常工作而无需任何额外代码

    【讨论】:

    • 我已经测试过了,但不是通过使用信号。我在内部MouseArea 上使用了onEntered 信号。如果鼠标进入内部MouseArea,外部的将悬停。但是,还有一个问题! onExited 信号将比onEntered 信号更早触发! onExited 边框在onEnter 边框内。
    • 我也考虑过这一点,并决定如果信号的顺序错误,它也不会正常工作。也许在外部项目中添加代码来监控子项目的悬停?
    • 谢谢@Jay。不成功
    【解决方案3】:

    为视图中元素的每个状态创建状态,然后您可以使用 if 语句或 case 语句来更改这些属性。换句话说,尽量不要将您的元素设置为在 MouseArea 上工作,而是在属性上工作并设置用于设置属性的元素属性我希望这会有所帮助,如果不是这里是示例:

    编辑我添加了透明的颜色。如果没有鼠标怎么办。如果我使用的是图像,我会使用不透明度然后添加一堆行为但这是一个工作

    例子

    import QtQuick 2.0
    Rectangle {
        width: 360
        height: 360
        property string state1:"OutMouse"
        property string state2: "OutMouse"
        property string state3: "OutMouse"
        property string state4: "OutMouse"
        Rectangle{
            id:blueRec
            width: parent.width
            height: parent.height / 6
            color: state1 === "InMouse" ? "blue" : "green"
            MouseArea{
                anchors.fill: blueRec
                hoverEnabled: true
                onEntered: state1 = "InMouse"
                onExited: {
                    if (state1 === state2 || state3 || state4){
                        state1 = "InMouse"
                    }
                    if(state1 !== state2 || state3 || state4)
                    {
                        state1 = "OutMouse"
                    }
                }
            }
            Text {
                text: state1=== "InMouse"? qsTr("foo") :"bar"
                anchors.centerIn: blueRec
            }
            Row{
                width: parent.width
                height: parent.height / 4
    
                spacing: 2
                anchors{
                    left: parent.left
                    verticalCenter:  blueRec.verticalCenter
                    leftMargin: blueRec.width / 12
                }
                Rectangle{
                    id: rec1
                    height: parent.height;
                    width: height
                    color: {
                        if  ( state3 === "InMouse")
                            return "gray"
                        if (state1 === "OutMouse")
                            return "transparent"
                        else
                            return "white"}
                    MouseArea{
                        id: rec1M
                        anchors.fill: parent
                        hoverEnabled: true
                        onEntered:{
                            state1 = "InMouse"
                            state2 = "InMouse"
                        }
                        onExited: state2 = "OutMouse"
                    }
                }
    
                Rectangle{
                    id: rec2
                    height: parent.height ;
                    width: height
                    color: {
                        if  (state3 === "InMouse")
                            return "gray"
                        if (state1 === "OutMouse")
                            return "transparent"
                        else
                            return "white"
                    }
                    MouseArea{
                        id: rec2M
                        anchors.fill: parent
                        hoverEnabled: true
                        onEntered:{
                            state1 = "InMouse"
                            state3 = "InMouse"
                        }
                        onExited: state3 = "OutMouse"
                    }
                }
    
                Rectangle{
                    id: rec3
                    height: parent.height;
                    width: height
                    color:{
                        if  (state4 === "InMouse")
                            return "gray"
                        if (state1 === "OutMouse")
                            return "transparent"
                        else
                            return "white"
                    }
                    MouseArea{
                        id:  rec3M
                        anchors.fill: parent
                        hoverEnabled: true
                        onEntered:{
                            state4 = "InMouse"
                            state1 = "InMouse"
                        }
                        onExited: state4 = "OutMouse"
                    }
                }
            }
        }
    }
    

    【讨论】:

      【解决方案4】:

      我遇到了同样的问题,并在QtQuick 5.0 documentation for MouseArea 中找到了答案。这个问题的答案其实很简单。

      如果您想在父 MouseArea 中包含子鼠标悬停事件,请将子 MouseArea 设置为父 MouseArea 的子:

      MouseArea {
          id: parent
      
          MouseArea {
              id: child
          }
      }
      

      由于我有一个自定义的 Widget 类型将用作父视图,因此我最终将 default 属性作为 MouseArea 的子级:

      Item {
          default property alias children: mouseArea.data
      
          MouseArea {
              id: mouseArea
          }
      }
      

      【讨论】:

      • 我不知道为什么!您可以看到我的示例代码使用了这种模式,但不起作用!但是它现在使用 Qt5.2.0 :) 对于其他感兴趣的用户,只需将内部 MouseArea 保留在外部一个内即可。仔细检查hoverEnabled: true,它会起作用。
      • 我不完全理解答案的任何一部分。第一部分:你的意思是If you want to include descendant mouse hover events in your ancestor MouseArea, make you child MouseArea a direct child of the parent MouseArea?如果是这样,您的第二个示例如何工作,考虑到它只包含 one MouseArea?
      • 我有一个用例,其中CheckBox 在列表的一行上,其中列表行会在悬停时突出显示。起初我将CheckBoxMouseArea 放在同一级别,但是一旦CheckBox 嵌套在MouseArea 中,hoverEnabled: true 被应用到封闭的MouseArea 这启用了悬停效果CheckBox,这个答案在 Qt5.9 上运行。
      • 可以确认这适用于 Qt 5.11.1。您可能希望拥有具有父鼠标区域和默认属性的基类,如第二个示例所示。这样,其后代中的所有项目都将成为主鼠标区域的子项。
      • 这很棒。在 5.12 QQC2 中像魅力一样工作
      猜你喜欢
      • 2018-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-22
      • 1970-01-01
      • 2012-04-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多