In MouseArea.onEntered,我能否检测事件触发的原因是否仅仅是 MouseArea 移动并在光标下,而不是相反的方向?
我想做这样的事情:(伪码)
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通过锚定定位/大小时,它不起作用。
发布于 2017-05-09 14:18:47
假设:
这只会影响边缘情况,即光标和
MouseArea都在移动。 我在这里的假设是,光标的移动是在MouseArea移动之前处理的。我没有任何确凿的证据证明这一点。只有我的测试和下面的解决方案,表明。
解决方案
第一个挑战是检测MouseArea的运动。它可能是移动的,而不改变它自己的x和y-values,例如,如果它的父程序正在移动。
为了解决这个问题,我将介绍两个属性globalX和globalX。然后我使用来自this answer on how to track a gobal position of an object的技巧。
现在我要处理两个信号:globalXChanged和globalYChanged。
根据我的假设,他们是在mouseXChanged和mouseYChanged之后被解雇的。我将使用一个标志isEntered来确保,如果第一个标记被触发,我只处理其中的一个,方法是将其设置为true。
我将使用globalMouseArea上的游标位置来确定游标是否在MouseArea的范围内。这要求,游标当时不在其他MouseArea 中,或者至少我知道它是。
->用这个,我已经成功地探测到了入口。
第二个挑战是检测出口。在这里,我们有四个案例需要区分:
MouseArea,因为它的运动。MouseArea的移动,光标进入并离开了MouseAreaMouseArea移动,而离开是因为光标移动。MouseArea的移动而离开。第一个问题很容易处理。当它进入时,我们处理entered,当它离开时,我们处理exited。但在米契提到的修复之后,我们不能再依赖这个了。
因此,我们不会设置hoverEnabled: true,并在光标移动或targetMouseArea移动时将光标的位置映射到targetMouseArea,并采取相应的行动。
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内单击时,只要按下按钮,就不会检测出离开。
发布于 2017-05-09 13:23:09
您可以检查自上次事件以来是否更改了mouseX、mouseY。
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)获取绝对值。
https://stackoverflow.com/questions/43869586
复制相似问题