16

Consider this C++ statement (example from docs):

QTimer::singleShot(600000, &app, SLOT(quit()));

How to do the same in .qml JavaScript, something like this QML:

Rectangle {
    property int counter: 0
    onCounterChanged: {
        if (counter > 42) {
            // do equivalent of above C++ statement here
        }
    }
    // more code, which actually manipulates counter 
}

There's the obvious solution of having separate Timer, which is then started by this JavaScript code, and I'll accept that as an answer if a one-liner is not possible. Is it?

hyde
  • 60,639
  • 21
  • 115
  • 176
  • 2
    The equivalent would be [Timer](http://doc.qt.io/qt-5/qml-qtqml-timer.html). Set `repeat: false` to get single shot behavior. – Pavel Strakhov Jun 10 '15 at 11:35
  • 1
    `repeat` is *false* by default, actually. – hyde Jun 10 '15 at 12:04
  • 1
    Nice question. `setTimeout`/`setInterval` are out of question since they cannot be used. You can consider [this answer](http://stackoverflow.com/a/28514691/2538363) as a - rather hackish - approach. By setting parameters in function signature you can reduce the usage to a single line, e.g. `delay(/*repeat*/ true, 12000, functionName)`. – BaCaRoZzo Jun 10 '15 at 12:16

6 Answers6

14

I ended up adding this to my main.qml:

Component {
    id: delayCallerComponent
    Timer {
    }
}

function delayCall( interval, callback ) {
    var delayCaller = delayCallerComponent.createObject( null, { "interval": interval } );
    delayCaller.triggered.connect( function () {
        callback();
        delayCaller.destroy();
    } );
    delayCaller.start();
}

Which can be used like this:

delayCall( 1000, function () { ... } );
Ivan Kolev
  • 191
  • 1
  • 6
12

Change "repeat" property to false for Timer object.

import QtQuick 1.0

Item {
    Timer {
        id: timer
        interval: 600000
        running: false
        repeat: false
        onTriggered: Qt.quit()
    }

    Rectangle {
        property int counter: 0
        onCounterChanged: {
            if (counter > 42) {
                timer.running = true
            }
        }
    }
}
hyde
  • 60,639
  • 21
  • 115
  • 176
synacker
  • 1,722
  • 13
  • 32
3

Here is how to do it using a SequentialAnimation element:

SequentialAnimation {
    id: quitTimer
    PauseAnimation { duration: 60000 }
    ScriptAction { script: Qt.quit() }
}

Rectangle {
    property int counter: 0
    onCounterChanged: {
        if (counter > 42) {
            quitTimer.start()
        }
    }
}

If that's too ugly, make a component out of it:

// SingleshotTimer.qml
import QtQuick 2.0
SequentialAnimation {
    property alias delay: delayAnim.duration
    property alias script: scriptAction.script

    PauseAnimation { id: delayAnim; duration: 10000 }
    ScriptAction { id: scriptAction }
}

Using this new component gives what you want:

SingleshotTimer { id: timer; delay: 60000; script: Qt.quit() }

Rectangle {
    property int counter: 0
    onCounterChanged: {
        if (counter > 42) {
            timer.start()
        }
    }
} 
pixelgrease
  • 1,940
  • 23
  • 26
1

there is a timer component in QML

import QtQuick 2.0

Item {
    Timer {
        interval: 500; running: true; repeat: true
        onTriggered: time.text = Date().toString()
    }

    Text { id: time }
}

for more details see the documentation

Sherif O.
  • 506
  • 4
  • 15
1

Another option I came up with is to simply define a function like this in C++:

void QmlUtils::singleShot(int msec, QJSValue callback)
{
    QTimer::singleShot(msec, this, [callback] () mutable {
        if (callback.isCallable())
            callback.call();
    });
}

and I call it from QML with:

lqtUtils.singleShot(5000, () => console.log("Hello!"))

I then added that C++ function to my collection of "must-have" here: https://github.com/carlonluca/lqtutils/blob/master/lqtutils_ui.h#L53.

Luca Carlon
  • 9,546
  • 13
  • 59
  • 91
0

I set properties like this running: true; repeat: false;

    Timer {
      interval: 5000 
      running: true
      repeat: false
      onTriggered:console.log("Test");
    }
Joe
  • 811
  • 1
  • 8
  • 14