我有一些兄弟Rectangle元素,具有半径属性,因此它们显示为圆形。每个元素都有一个子项,该子项具有一个子MouseArea,其目的是实现“圆形鼠标区域”效果(原始SO答案)。Item和MouseArea被检测到,以便点击和拖动仅在Rectangle可见的圆形形状内生效,而不是在Rectangle的实际占地面积内生效。
不幸的是,在下面的示例中出现了故障。当在点处拖动时,期望的结果是移动圆形1,并且在大多数情况下会发生这种情况。但是,如果您创建了圆形1然后创建了圆形2,然后将鼠标光标移动到点上,则不会发生这种情况。如果您这样做并尝试拖动或单击,则您的交互将穿透到背景全窗口MouseArea并创建一个新圆形。 这个问题的原因是,当鼠标光标从圆形#2移动到点时,圆形#1的MouseArea的mouseX和mouseY没有更新。当圆形#2允许点击向下传播时,它会击中圆形#1的矩形,但然后圆形#1的项声明containsMouse为false,并再次向下传播。
只要鼠标光标离开圆形#2边界矩形的范围,例如向上或向左移动一点,圆形#1的MouseArea就会得到更新,并且其containsMouse变为true,然后它开始重新捕捉点击和拖动事件。
我已经尝试了一些潜在的解决方案,但都没有比下面的代码更进一步。
不幸的是,在下面的示例中出现了故障。当在点处拖动时,期望的结果是移动圆形1,并且在大多数情况下会发生这种情况。但是,如果您创建了圆形1然后创建了圆形2,然后将鼠标光标移动到点上,则不会发生这种情况。如果您这样做并尝试拖动或单击,则您的交互将穿透到背景全窗口MouseArea并创建一个新圆形。 这个问题的原因是,当鼠标光标从圆形#2移动到点时,圆形#1的MouseArea的mouseX和mouseY没有更新。当圆形#2允许点击向下传播时,它会击中圆形#1的矩形,但然后圆形#1的项声明containsMouse为false,并再次向下传播。
只要鼠标光标离开圆形#2边界矩形的范围,例如向上或向左移动一点,圆形#1的MouseArea就会得到更新,并且其containsMouse变为true,然后它开始重新捕捉点击和拖动事件。
我已经尝试了一些潜在的解决方案,但都没有比下面的代码更进一步。
import QtQuick 2.12
import QtQuick.Controls 2.5
ApplicationWindow {
visible: true
width: 640
height: 480
property real spotlightRadius: 100
MouseArea {
visible: true
anchors.fill: parent
onClicked: {
spotlightComponent.createObject(parent, {
"x": x + mouseX - spotlightRadius,
"y": y + mouseY - spotlightRadius,
"width": spotlightRadius * 2,
"height": spotlightRadius * 2
})
}
}
Component {
id: spotlightComponent
Rectangle {
id: spotlightCircle
visible: true
x: parent.x
y: parent.y
width: parent.width
height: parent.height
radius: Math.max(parent.width, parent.height) / 2
color: Qt.rgba(Math.random()*0.5+0.5,Math.random()*0.5+0.5,Math.random()*0.5+0.5,0.5);
Item {
anchors.fill: parent
drag.target: parent
onDoubleclicked: parent.destroy()
onWheel: { parent.z += wheel.pixelDelta.y; currentSpotlight = parent }
property alias drag: mouseArea.drag
//FIXME when moving the mouse out of a higher element's containsMouse circle
// but still inside its mouseArea.containsMouse square, lower elements'
// mouseArea do not update, so their containsMouse doesn't update, so clicks
// fall through when they should not.
property bool containsMouse: {
var x1 = width / 2;
var y1 = height / 2;
var x2 = mouseArea.mouseX;
var y2 = mouseArea.mouseY;
var deltax = x1 - x2;
var deltay = y1 - y2;
var distance2 = deltax * deltax + deltay * deltay;
var radius2 = Math.pow(Math.min(width, height) / 2, 2);
return distance2 < radius2;
}
signal clicked(var mouse)
signal doubleclicked(var mouse)
signal wheel(var wheel)
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
//FIXME without acceptedButtons, propagated un-accepted clicks end up with the wrong coordinates
acceptedButtons: parent.containsMouse ? Qt.LeftButton : Qt.NoButton
propagateComposedEvents: true
onClicked: { if (parent.containsMouse) { parent.clicked(mouse) } else { mouse.accepted = false } }
onDoubleClicked: { if (parent.containsMouse) { parent.doubleclicked(mouse) } }
onWheel: { if (parent.containsMouse) { parent.wheel(wheel) } }
drag.filterChildren: true
}
}
}
}
}