Measuring elapsed time in QML

marmistrz picture marmistrz · Jun 23, 2015 · Viewed 13.5k times · Source

Let's consider the following example: we have a Qt Quick Controls Button. The user clicks it twice within 5 seconds. After pushing the Button for the first time, the QML Timer is running for these 5 seconds. We want to measure the time elapsed between two clicks, with a millisecond accuracy.

Unfortunately, the QML Timer can't show us the elapsed time.

As suggested on the BlackBerry forums, it would be possible to compare the dates. This isn't very handy, though, since the first click might occur on 31 Dec 2015, 23:59:55 and the second on 1 Jan 2016, 00:00:05 and the check would have to be complex.

Is there any better option?

Answer

BaCaRoZzo picture BaCaRoZzo · Jun 24, 2015

As explained in the comments, QML Timer is not suitable for your specific needs since it is synchronized with the animation timer (further details here) and thus its resolution is dependent on animation timer as well.

@qCring solution is for sure satisfying and I would prefer such an approach, if an higher precision is needed or a better performance (see also this answer and the interesting link at the bottom about improving precision).

However, given your requirements, a pure QML/JS approach is perfectly feasible. In this case you can exploit JavaScript Date, both because it's easy to calculate elapsed time, using getTime(), but also because QML fully supports JS Date and also extends it with some useful functions.

Here is a simple example:

import QtQuick 2.4
import QtQuick.Window 2.2
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.3

ApplicationWindow {
    width: 300
    height: 300
    visible: true

    property double startTime: 0

    ColumnLayout {
        anchors.fill: parent

        Text {
            id: time
            font.pixelSize: 30
            text: "--"
            Layout.alignment: Qt.AlignCenter
        }

        Button {
            text: "Click me!"
            Layout.alignment: Qt.AlignCenter

            onClicked: {
                if(startTime == 0){
                    time.text = "click again..."
                    startTime = new Date().getTime()
                } else {
                    time.text = new Date().getTime() - startTime + " ms"
                    startTime = 0
                }
            }
        }
    }
}