我有一些具有radius属性的同级Rectangle元素,因此它们显示为圆形。每个子项都有一个子项,该子项具有一个子MouseArea,该项的目的是实现“圆形鼠标区域”效果(original SO answer)。对Item和MouseArea进行检测后,单击和拖动将仅在Rectangle的可见圆形形状内生效,而不在Rectangle的实际占用空间的边界框内生效。
不幸的是,下面显示了一个小故障。在圆点上拖动时,期望的结果是使圆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
}
}
}
}
}
答案 0 :(得分:1)
这不是解决您问题的确切方法,但这是我克服问题根源的方法。
在我的应用程序中,有一个MouseArea
与场景的一大块QQuickFrameBufferObject
重叠。这是我绘制3D场景的地方。由于您无法在QML中传播QHoverEvent
,因此必须使用onPositionChanged
处理程序捕获位置改变信号,并在C ++中调用一个方法,该方法将发送{{1 }}到必填项。
QML:
QHoverEvent
C ++:
MouseArea {
onPositionChanged: {
model.sendHoverEvent(Qt.point(mouse.x, mouse.y))
}
}
答案 1 :(得分:0)
您需要拒绝基础pressed
的{{1}}事件。它足以解决您的问题。如果按下事件被拒绝,则单击将自动转发给基础兄弟项目。 MouseArea
和propagateComposedEvents
对您而言毫无用处。
请注意,如果wheel事件导致SpotlightCircle的z坐标小于0,它将不再接受鼠标事件,因为它们将被“ Creation” filterChildren
MouseArea
答案 2 :(得分:0)
我认为在这种情况下使用 HoverHandler 代替 MouseArea 可以提供所需的结果,因为它们按您的预期堆叠,即它们对于鼠标移动完全“透明”,也不会被任何 MouseArea 阻挡恰好在上面。