1

I would like to do something the moment the scrolling of a QML ScrollView has ended. From the documentation I assume that flickableItem.onMovementEnded is what I'm looking for but I never get that signal. Am I understanding "Movement" wrong? I have written this minimal QML application and my console.log gets never called. I run this on a Mac with Qt 5.7 or 5.5.1.

import QtQuick 2.5
import QtQuick.Controls 1.4

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    ScrollView {
        id: scrollView

        anchors.fill: parent

        flickableItem.onMovementEnded: {
            console.log("onMovementEnded")
        }

        Rectangle {
            id: rect

            width: 3000
            height: 3000
        }
    }

}

I also tried to connect it via "Connections" with no luck.

Connections {
    target: scrollView.flickableItem
    onMovementEnded: {
        console.log("onMovementEnded")
    }
}
jpnurmi
  • 5,716
  • 2
  • 21
  • 37
philipp
  • 119
  • 1
  • 6

2 Answers2

2

From the documentation:

A ScrollView can be used either to replace a Flickable or decorate an existing Flickable.

...

flickableItem : Item

The flickableItem of the ScrollView. If the contentItem provided to the ScrollView is a Flickable, it will be the contentItem.

Sounds to me that the flickableItem property will be populated only if the scroll view is used in conjunction with a Flickable. And in your code it is not.

EDIT: After investigating a little I found out that the property is there even if you don't use a Flickable, but the signal will only be emitted if you have an actual Flickable inside the ScrollView and it will only be emitted when you scroll quickly from all the way from top to bottom or back using the mouse wheel, flicking won't do it, using the scrollbar won't do it. Not ideal, kind of buggy...

Seems that what you really want is to just use a Flickable and put manually scrollbars on it, there are plenty of examples how to do it. And then it will always emit when it comes to a stop.

dtech
  • 47,916
  • 17
  • 112
  • 190
  • Thank you for your input @ddriver. Yes, it looks like a bug. I didn't exchange the Flickable as you wrote and tried scrolling quickly from top to bottom or vise versa and I get the `onMovementEnded` event only when the scroll view over shoots and bounces back. – philipp Sep 19 '16 at 10:50
  • 2
    Yes, only when it overshoots, that means the actual scrolling doesn't really affect the flickable until the scrollbar reaches the end, and only the overshoot reaches it. As with so many things in my experience with QML - you have to do it yourself in order to suit your needs. Stock QML components are pretty much useless outside of their narrow intended use. – dtech Sep 19 '16 at 10:54
0

Based on @ddriver's input, I build a solution using onContentYChanged and a Timer. This is sufficient for me even though it is not perfect.

import QtQuick 2.5
import QtQuick.Controls 1.4

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    ScrollView {
        id: scrollView

        anchors.fill: parent

        flickableItem.onContentXChanged: {
            updateContentDelay.restart()
        }

        flickableItem.onContentYChanged: {
            updateContentDelay.restart()
        }

        Rectangle {
            id: rect

            width: 3000
            height: 3000
        }
    }

    Timer {
        id: updateContentDelay
        interval: 200
        repeat: false

        onTriggered: {
            console.log("do something")
        }
    }

}
philipp
  • 119
  • 1
  • 6