Qt 在MouseArea.onenterned中,检测原因是否只是*MouseArea*移动并位于光标下方
在MouseArea.onenterned中,我能否检测到触发事件的原因是否只是MouseArea移动并位于光标下方,而不是相反 我想做这样的事情:(伪代码) 但这使得假设输入的Qt 在MouseArea.onenterned中,检测原因是否只是*MouseArea*移动并位于光标下方,qt,input,qml,mouseevent,qtquick2,Qt,Input,Qml,Mouseevent,Qtquick2,在MouseArea.onenterned中,我能否检测到触发事件的原因是否只是MouseArea移动并位于光标下方,而不是相反 我想做这样的事情:(伪代码) 但这使得假设输入的将在鼠标eaeaeaposchange之后和在窗口之前被触发。我对这个假设没有信心 此外,当MouseArea的祖先移动时,或者当MouseArea通过锚定进行定位/调整大小时,它也不起作用。您可以检查自上次事件以来是否更改了mouseX,mouseY property int previousMouseX = mous
将在鼠标eaeaeaposchange
之后和在窗口之前被触发。我对这个假设没有信心
此外,当MouseArea的祖先移动时,或者当MouseArea通过锚定进行定位/调整大小时,它也不起作用。您可以检查自上次事件以来是否更改了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)
获取绝对值。假设:
这只影响边缘情况,即光标和鼠标earea都在移动。
我在这里的假设是,光标的移动是在移动MouseArea
之前处理的。我没有任何确切的证据证明这一点。只有我用下面的解决方案进行的测试表明
解决方案
第一个挑战是检测鼠标earea
的移动。它可能会移动,而自身的x
和y
值不会改变,例如,如果其父对象正在移动。
为了解决这个问题,我将介绍两个属性globalX
和globalX
。然后我使用了来自的技巧
现在我要处理两个信号:globalXChanged
和globalYChanged
根据我的假设,在mouseXChanged
和mouseYChanged
之后,他们会被解雇。我将使用一个标志isEntered
,确保在第一个被触发时,我只处理其中一个,方法是将其设置为true
我将使用globalMouseArea
上的光标位置来确定光标是否在MouseArea
的范围内这需要,光标当时不在其他MouseArea
中,或者至少我知道它
->有了这个,我已经成功地探测到了入口
第二个挑战是检测出口。这里我们有4个案例需要区分:
光标进入和离开MouseArea
,因为它在移动
由于MouseArea
光标进入是因为MouseArea
移动,离开是因为光标移动
光标进入是因为它移动了,离开是因为MouseArea
移动了
第一个很容易处理。在它进入后,我们处理进入的,当它离开时,我们处理退出的。但是在米奇提到的修复之后,我们不能再依赖它了
因此,我们不会在光标移动或targetMouseArea
移动时设置hoverEnabled:true
并将光标位置映射到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
}
}
导入QtQuick 2.7
导入QtQuick.Controls 2.0
应用程序窗口{
id:根
可见:正确
宽度:400;高度:450
鼠耳{
id:globalMouseArea
锚定。填充:父级
hoverEnabled:true
onClicked:ani.restart()
}
长方形{
x:300
y:300
宽度:50
身高:50
颜色:“绿色”
}
长方形{
id:rect
宽度:50
身高:50
颜色:“红色”
正文{
text:targetMouseArea.isEntered.toString()
}
鼠耳{
id:targetMouseArea
锚定。填充:父级
自运动输入的信号
MouseMovement输入的信号
onenteredbymouseMotation:console.log('原因:鼠标')
onEnteredBySelfMovement:console.log('原因:Self')
globalPos酒店点:{
变量c=Qt.点(0,0)
var itm=此
for(;itm.parent!==null;itm=itm.parent){
c、 x+=itm.x
c、 y+=itm.y
}
返回c
}
属性布尔值已居中:false
函数检查冲突(sig){
if((globalPos.yglobalMouseArea.mouseY)
&&(globalPos.xglobalMouseArea.mouseX)){
如果(!isEntered){
isEntered=true
sig()
}
}
else if(isEntered&!containsMouse){
console.log(isEntered=false)
}
}
OnglobalPosted:{
检查碰撞(由selfmovement输入)
}
联系{
目标:环球大厦区
已更改的位置:{
targetMouseArea.checkCollision(targetMouseArea.enteredByMouseMovement)
}
}
}
}
数字化{
id:ani
目标:rect
属性:“x,y”
起:0
收件人:300
跑步:对
持续时间:10000
}
}
遗留问题:当我们在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
}
}