I have some items in the scene:
Rectangle {
x: 20
y: 20
width: 20
height: 20
color: 'red'
Rectangle {
x: 5
y: 10
width: 5
height: 5
color: 'green'
}
}
now I would like to know: given a (x, y) coordinate, which is the topmost visible item that renders something at that coordinate?
E.g.:
- for
(21, 21)
that would be the redRectangle
- for
(26, 32)
that would be the greenRectangle
- for
(15, 15)
that would be nothing
does Qt Quick offers a simple function to do this?
If not, consider the possibility to add MouseArea
s that fill the rectangles.
Can I synthesize a press event with specific (x, y) coordinate? This would be even better.
CodePudding user response:
I think what you need is amongst the methods of Qml Item . You should take a look at the childAt method or the visibleChildren property.
CodePudding user response:
Since Item.childAt(...)
is broken in this regard, and it has a bug report opened 10 years ago and not yet fixed, I came up with this workaround:
function traverseItemTreeWithClipping(item, pt, f, rootItem) {
rootItem = rootItem || item
var p = item.mapFromItem(rootItem, pt)
var inItemRect = p.x >= 0 && p.y >= 0 && p.x < item.width && p.y < item.height
if(item.clip && !inItemRect) return
f(item, p, inItemRect)
for(var i = 0; i < item.children.length; i )
traverseItemTreeWithClipping(item.children[i], pt, f, rootItem)
}
function hitTest(rootItem, pt) {
var result = undefined
var z = -Infinity
traverseItemTreeWithClipping(rootItem, pt, (item, p, inItemRect) => {
if(item.visible && item.z >= z && inItemRect) {
result = item
z = item.z
}
})
return result
}
which takes into account the z
property of items, returning the truly visible Item.