Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

QML InputHandler stop propagation of event

I have two Rectangles, each with a TapHandler. Rectangle A is the parent of Rectangle B
How can I configure A and B, so that when B is clicked, the EventPoint does not propagate to the onSingleTapped handler of A?

The EventPoint docs suggest to set its accepted property to true:

Setting accepted to true prevents the event from being propagated to Items below the PointerHandler's Item.

However, at the same time the docs state that accepted is a read-only property, which does not make much sense (I guess the documentation is out-of-date or simply wrong).

TestCode:

Rectangle {
    id: a

    width: 200
    height: 200
    color: "yellow"
    TapHandler {
        onSingleTapped: console.log("A tapped")
    }

    Rectangle {
        id: b
        color: "blue"
        width: 100
        height: 100
        TapHandler {
            onSingleTapped: function(eventPoint) {
                // Stop propagation.
                eventPoint.accepted = true
                console.log("B tapped")
            }
        }
    }
}

UPDATE: Setting the gesturePolicy of B to TapHandler.ReleaseWithinBounds prevents A from receiving the event. Not sure if this really the best solution

like image 974
skaldesh Avatar asked Dec 27 '20 16:12

skaldesh


2 Answers

For Handlers, the entire event is delivered to each handler; therefore Handlers accept individual points, not the whole event. In general, accepting all points implies accepting the entire event, but it may be that one handler accepts some points while another accepts other points. delivery is not “done” until all the points are accepted.

It looks like setting grabPermissions without a gesturePolicy does not do what's expected .. grab the event and preventing propagation to other items.

Changing Rectnagle b (a's child) TapHandler to have gesturePolicy: TapHandler.ReleaseWithinBounds TapHandler.WithinBounds seems the right way to aaccept, in other words this way it accepts the point, that means the event will not propagate to the TapHandler of the parent Rectangle!

    Rectangle {
        id: b
        z:2
        color: "blue"
        width: 100
        height: 100
        TapHandler {
            gesturePolicy: TapHandler.ReleaseWithinBounds | TapHandler.WithinBounds
            grabPermissions: PointerHandler.CanTakeOverFromAnything | PointerHandler.CanTakeOverFromHandlersOfSameType | PointerHandler.CanTakeOverFromItems
                             | PointHandler.ApprovesTakeOverByAnything | PointHandler.ApprovesCancellation
            onSingleTapped: function(eventPoint) {
                // Stop propagation.
                eventPoint.accepted = true // this is just a confirmation!
                console.log("B tapped")
            }
        }
    }

further from .. narkive interset group

like image 62
Mohammad Kanan Avatar answered Nov 15 '22 02:11

Mohammad Kanan


Qt makes a difference between active and passive touch point / pointer grabs. grabPermissions only affect active grabbers. TapHandler is passive with the default gesturePolicy, and active otherwise. That's why you need to change the gesturePolicy in a TapHandler to see any grabPermissions in effect, even the default ones.

Other input handlers don't have this same quirk, but have others. While each handler is simpler than a MouseArea or MultiPointTouchArea as Qt intended, interactions between layered handlers became much more complicated than between layered Area instances. So, for complex input, I'm using an Area instead. Which one depends on whether I'm handling hover or multitouch.

Active and passive grabs: https://doc.qt.io/qt-6/qtquickhandlers-index.html#pointer-grab
TapHandler behavior: https://doc.qt.io/qt-6/qml-qtquick-taphandler.html#details

like image 2
really Avatar answered Nov 15 '22 02:11

really