Search code examples
javascriptqmldelay

How to create delay function in QML?


I would like to create a delay function in javascript that takes a parameter of amount of time to delay, so that I could use it do introduce delay between execution of JavaScript lines in my QML application. It would perhaps look like this:

function delay(delayTime) {
  // code to create delay
}

I need the body of the function delay(). Note that setTimeout() of JavaScript doesn't work in QML.


Solution

  • As suggested in the comments to your question, the Timer component is a good solution to this.

    function Timer() {
        return Qt.createQmlObject("import QtQuick 2.0; Timer {}", root);
    }
    
    timer = new Timer();
    timer.interval = 1000;
    timer.repeat = true;
    timer.triggered.connect(function () {
        print("I'm triggered once every second");
    })
    
    timer.start();
    

    The above would be how I'm currently using it, and here's how I might have implemented the example in your question.

    function delay(delayTime) {
        timer = new Timer();
        timer.interval = delayTime;
        timer.repeat = false;
        timer.start();
    }
    

    (Which doesn't do anything; read on)

    Though, the exact way you are looking for it to be implemented suggests that you are looking for it to block until the next line of your program executes. But this isn't a very good way to go about it as it would also block everything else in your program as JavaScript only runs in a single thread of execution.

    An alternative is to pass a callback.

    function delay(delayTime, cb) {
        timer = new Timer();
        timer.interval = delayTime;
        timer.repeat = false;
        timer.triggered.connect(cb);
        timer.start();
    }
    

    Which would allow you to use it as such.

    delay(1000, function() {
        print("I am called one second after I was started.");
    });
    

    The above assumes you're working in a separate JavaScript file that you later import into your QML file. To do the equivalent in a QML file directly, you can do this.

    import QtQuick 2.0
    
    Rectangle {
        width: 800
        height: 600
    
        color: "brown"
    
        Timer {
            id: timer
        }
    
        function delay(delayTime, cb) {
            timer.interval = delayTime;
            timer.repeat = false;
            timer.triggered.connect(cb);
            timer.start();
        }
    
        Rectangle {
            id: rectangle
            color: "yellow"
            anchors.fill: parent
            anchors.margins: 100
            opacity: 0
    
            Behavior on opacity {
                NumberAnimation {
                    duration: 500
                }
            }
        }
    
        Component.onCompleted: {
            print("I'm printed right away..")
            delay(1000, function() {
                print("And I'm printed after 1 second!")
                rectangle.opacity = 1
            })
        }
    }
    

    I'm not convinced that this is the solution to your actual problem, however; to delay an animation, you could use PauseAnimation.