Qml timer not triggered in the right interval

dfranca picture dfranca · Mar 31, 2014 · Viewed 11.2k times · Source

I've created a timer QML app, and I'm using Timer qml component. The interval is set to 1000 milliseconds (the default one)... but it seems to be working properly only when the app is with focus on it. When I put it in background it seems that it's not triggered every time, and because of that I got some mistakes in the app.

I've tried to find anything related to that in the documentation, but I couldn't The timer code is really simple:

Timer {
    id: timer
    repeat: true
    onTriggered: {msRemaining -= 1000; Core.secondsToText(type);}
}

Anyone has any idea about that and how to fix it?

Versions: Qt 5.2 QML 2.0 OS X 10.9

Answer

Nejat picture Nejat · Mar 31, 2014

The QML Timer element is synchronized with the animation timer. Since the animation timer is usually set to 60fps, the resolution of Timer will be at best 16ms. You should also note that in Qt Quick 2 the animation timer is synced to the screen refresh (while in Qt Quick 1 it is hard-coded to 16ms). So when your app runs in background i think the refreshing is stopped and consequently your timer which is synced to screen refresh will stop working properly.

If you want to show elapsed time using a timer as you did is not a good idea because it is not precise. You can use javascript Date() function like:

import QtQuick 2.0

Item  {
    id: root
    width: 200; height: 230

    property double startTime: 0
    property int secondsElapsed: 0

    function restartCounter()  {

            root.startTime = 0;

        }

    function timeChanged()  {
        if(root.startTime==0)
        {
            root.startTime = new Date().getTime(); //returns the number of milliseconds since the epoch (1970-01-01T00:00:00Z);
        }
        var currentTime = new Date().getTime();
        root.secondsElapsed = (currentTime-startTime)/1000;
    }

    Timer  {
        id: elapsedTimer
        interval: 1000;
        running: true;
        repeat: true;
        onTriggered: root.timeChanged()
    }

    Text {
        id: counterText
        text: root.secondsElapsed
    }
}