首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在MouseArea.onEntered中,检测原因是否仅是*MouseArea*移动并移到光标下面

在MouseArea.onEntered中,检测原因是否仅是*MouseArea*移动并移到光标下面
EN

Stack Overflow用户
提问于 2017-05-09 12:15:40
回答 2查看 738关注 0票数 1

In MouseArea.onEntered,我能否检测事件触发的原因是否仅仅是 MouseArea 移动并在光标下,而不是相反的方向?

我想做这样的事情:(伪码)

代码语言:javascript
复制
    MouseArea {
        // ...
        property bool positionDirty = false
        Connections {
            target: window
            onAfterRendering: {
                positionDirty = false;
            }
        }
        onMouseAreaPosChanged: {
            positionDirty = true;
        }
        onEntered: {
            if(positionDirty) {
                positionDirty = false;
                return;
            }
            // handle event here
        }
    }

但这使得这样的假设:entered将在 mouseAreaPosChanged之后被解雇,将在 window.afterRendering之前被解雇。我对这个假设没有信心。

而且,当MouseArea的祖先移动,或者当MouseArea通过锚定定位/大小时,它不起作用。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-05-09 14:18:47

假设:

这只会影响边缘情况,即光标和MouseArea都在移动。 我在这里的假设是,光标的移动是在MouseArea移动之前处理的。我没有任何确凿的证据证明这一点。只有我的测试和下面的解决方案,表明。

解决方案

第一个挑战是检测MouseArea的运动。它可能是移动的,而不改变它自己的xy-values,例如,如果它的父程序正在移动。

为了解决这个问题,我将介绍两个属性globalXglobalX。然后我使用来自this answer on how to track a gobal position of an object的技巧。

现在我要处理两个信号:globalXChangedglobalYChanged

根据我的假设,他们是在mouseXChangedmouseYChanged之后被解雇的。我将使用一个标志isEntered来确保,如果第一个标记被触发,我只处理其中的一个,方法是将其设置为true

我将使用globalMouseArea上的游标位置来确定游标是否在MouseArea的范围内。这要求,游标当时不在其他MouseArea 中,或者至少我知道它是。

->用这个,我已经成功地探测到了入口。

第二个挑战是检测出口。在这里,我们有四个案例需要区分:

  1. 游标进入并离开MouseArea,因为它的运动。
  2. 由于MouseArea的移动,光标进入并离开了MouseArea
  3. 游标进入是因为MouseArea移动,而离开是因为光标移动。
  4. 游标进入是因为它移动,并且随着MouseArea的移动而离开。

第一个问题很容易处理。当它进入时,我们处理entered,当它离开时,我们处理exited。但在米契提到的修复之后,我们不能再依赖这个了。

因此,我们不会设置hoverEnabled: true,并在光标移动或targetMouseArea移动时将光标的位置映射到targetMouseArea,并采取相应的行动。

代码语言:javascript
复制
import QtQuick 2.7
import QtQuick.Controls 2.0

ApplicationWindow {
    id: root
    visible: true
    width: 400; height: 450
    MouseArea {
        id: globalMouseArea
        anchors.fill: parent
        hoverEnabled: true
        onClicked: ani.restart()
    }

    Rectangle {
        x: 300
        y: 300
        width: 50
        height: 50
        color: 'green'
    }

    Rectangle {
        id: rect
        width: 50
        height: 50
        color: 'red'

        Text {
            text: targetMouseArea.isEntered.toString()
        }

        MouseArea {
            id: targetMouseArea
            anchors.fill: parent
            signal enteredBySelfMovement
            signal enteredByMouseMovement

            onEnteredByMouseMovement: console.log('Cause: Mouse')
            onEnteredBySelfMovement: console.log('Cause: Self')

            property point globalPos: {
                var c = Qt.point(0, 0)
                var itm = this
                for (; itm.parent !== null; itm = itm.parent) {
                    c.x += itm.x
                    c.y += itm.y
                }
                return c
            }
            property bool isEntered: false

            function checkCollision(sig) {
                if ((globalPos.y < globalMouseArea.mouseY)
                    && (globalPos.y + height > globalMouseArea.mouseY)
                    && (globalPos.x < globalMouseArea.mouseX)
                    && (globalPos.x + width > globalMouseArea.mouseX)) {
                    if (!isEntered) { 
                        isEntered = true
                        sig()
                    }
                }
                else if (isEntered && !containsMouse) {
                    console.log(isEntered = false)
                }
            }

            onGlobalPosChanged: {
                checkCollision(enteredBySelfMovement)
            }

            Connections {
                target: globalMouseArea
                onPositionChanged: {
                    targetMouseArea.checkCollision(targetMouseArea.enteredByMouseMovement)
                }
            }
        }
    }

    NumberAnimation {
        id: ani
        target: rect
        properties: 'x,y'
        from: 0
        to: 300
        running: true
        duration: 10000
    }
}

问题左:当我们在targetMouseArea内单击时,只要按下按钮,就不会检测出离开。

票数 2
EN

Stack Overflow用户

发布于 2017-05-09 13:23:09

您可以检查自上次事件以来是否更改了mouseXmouseY

代码语言:javascript
复制
property int previousMouseX = mouseX; // or use other values to init
property int previousMouseY = mouseY; // e.g., 0, x, parent.x, 
                                      // or set it from extern

onEntered() {
    if (mouseX != previousMouseX || mouseY != previousMouseY) {
       // TODO do something
        previousMouseX = mouseX;
        previousMouseY = mouseY;
    }
}

如果是mouseX,则mouseY相对于鼠标区域0,0,您可以使用mapFromItem(null, 0, 0)获取绝对值。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43869586

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档