7

I'm implementing gesture catcher (swipe left/right) with MouseArea. It should work inside Flickable with vertical flickableDirection. Also it should propagate mouse events to other elements beneath it in visual stack order. The problem is that child mouseArea with propagateComposedEvents set to true is blocking any parent's flicks before exact one click is made. After first click is made it's working correctly. Here is simplified code that is showing this.

import QtQuick 2.4
import QtQuick.Window 2.2

Window {
    id: __root
    visible: true
    width: 460; height: 640

    Flickable {
        id: mainFlickable

        width: parent.width
        height: parent.height
        contentHeight: column.height
        flickableDirection: Flickable.VerticalFlick

        MouseArea {
            anchors.fill: parent
            propagateComposedEvents: true
            z: 1
        }

        Column {
            id: column

            width: parent.width

            Repeater {
                model: 5

                Rectangle {
                    width: __root.width
                    height: 200

                    color: "yellow"
                    border.width: 2

                    MouseArea {
                        anchors.fill: parent

                        onClicked: {
                            console.log("clicked")
                        }
                    }
                }
            } //repeater
        } //column
    } //flickable
} //window

I spent quite some time trying to fix this and will appreciate any help. Thanks in advance!

rsht
  • 1,522
  • 12
  • 27
  • 1
    +1 for the working code: that's a time saver! As for the problem, it smells like a bug to me. `Pressed` events are *automatically* accepted and that's what happens the first time, i.e. the outer `MouseArea` eats up the event. After that the `Flickable` gains control. It seems like the `Flickable` needs a "warm up". Not sure if focusing can help. Possible workaround, hoping it does not break your use case, is the addition of `onPressed: mouse.accepted = false` to the outer `MouseArea` to always propagate `pressed` events. – BaCaRoZzo Mar 24 '15 at 16:34
  • Thanks for your answer! Although Flickable works with this workaround, it will break my code, because I won't be getting `positionChanged` and `released` signals if mouse is rejected on the press. I was trying to reject it only if some distance is made on XAxis (in onPositionsChanged) but it doesn't work there. Also, focusing isn't helping. – rsht Mar 24 '15 at 17:12
  • Focusing is a pain in the neck. I was also trying to use it. Uhm...can't you use the `drag` + `MouseX` to intercept the swipes? – BaCaRoZzo Mar 24 '15 at 17:17
  • Sorry, didn't quite get what you mean by that. Isn't `propagateComposedEvents` will be need in that case as well? – rsht Mar 24 '15 at 17:36
  • You said that you need `positionChanged`. I thought it was for dragging purposes. If that is the case I considered the possibility to just use `drag` AND use the provided workaround. Here I'm supposing you are implementing swipe in the outer `MouseArea`. Am I missing something (or everything)? – BaCaRoZzo Mar 24 '15 at 20:06
  • I'm using it for dragging as well as for mouse position changes recording (before Flickable steal mouseEvent from it). However, I found workaround that works fine for me so far (see below). Thank you so much for you help! – rsht Mar 24 '15 at 20:21
  • Ok! :) Since the answer solves your issue please mark it as accepted. – BaCaRoZzo Mar 24 '15 at 20:27
  • Nope...mark YOUR answer as accepted if it is the one that solves the problem, not another. Lol – BaCaRoZzo Mar 24 '15 at 20:29
  • 1
    Sry, didn't mean to do that :). However, I can't accept my answer for two days. Will do after that term. – rsht Mar 24 '15 at 20:34
  • Okay, the question is about : "The problem is that child mouseArea with propagateComposedEvents set to true is blocking any parent's flicks before exact one click is made." I don't understand why we need a warm up... Do you have any idea? – Antoine Morrier Dec 23 '19 at 10:35

2 Answers2

8

I found that following signal handler in MouseArea is a workaround for this and don't break my code:

onReleased: {
    if (!propagateComposedEvents) {
        propagateComposedEvents = true
    }
}

propagateComposedEvents should be set to false on the declaration (or ommited).

Thank you all for the efforts!

rsht
  • 1,522
  • 12
  • 27
1

I found little workaround for this. Hope it will fit your needs (at least until better solution will be provided).

Here is your updated code:

import QtQuick 2.4
import QtQuick.Window 2.2

Window {
    id: __root
    visible: true
    width: 460; height: 640

    Flickable {
        id: mainFlickable

        width: parent.width
        height: parent.height
        contentHeight: column.height
        flickableDirection: Flickable.VerticalFlick

        onDragStarted: ma.enabled = false
        onDragEnded: ma.enabled = true

        MouseArea {
            id: ma
            anchors.fill: parent
            enabled: false
            propagateComposedEvents: true
            z: 100

            onClicked: {
                print("CLICKED ON UPPER")
                mouse.accepted = false
            }
        }

        Column {
            id: column

            width: parent.width

            Repeater {
                model: 5

                Rectangle {
                    width: __root.width
                    height: 200

                    color: "yellow"
                    border.width: 2

                    MouseArea {
                        anchors.fill: parent                  
                        onClicked: console.log("clicked on child") 
                    }
                }
            } //repeater
        } //column
    } //flickable
} //window
NG_
  • 6,895
  • 7
  • 45
  • 67
  • 1
    `mouse.accepted = false` IS a workaround but will break my logic as it will block future `positionChanged` and `released` signals. Much thanks for the answer tho. – rsht Mar 24 '15 at 20:16