web-dev-qa-db-fra.com

Comment créer une fonction de délai dans QML?

Je souhaite créer une fonction de délai en javascript qui prend un paramètre de délai, de sorte que je puisse l'utiliser pour introduire un délai entre l'exécution des lignes JavaScript dans mon application QML. Cela ressemblerait peut-être à ceci:

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

J'ai besoin du corps de la fonction delay(). Notez que setTimeout() de javascript ne fonctionne pas dans QML.

17
Sнаđошƒаӽ

Comme suggéré dans les commentaires de votre question, le composant Timer est une bonne solution à cela.

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();

Ce qui précède serait la façon dont je l’utilise actuellement, et voici comment j’aurais pu implémenter l’exemple de votre question.

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

(Qui ne fait rien; lisez la suite)

Bien que la façon exacte dont vous cherchez à l'implémenter suggère que vous le cherchez pour bloquer jusqu'à l'exécution de la ligne suivante de votre programme. Mais ce n’est pas un très bon moyen de s’y prendre car cela bloquerait également tout le reste dans votre programme, car JavaScript ne fonctionne que dans un seul thread d’exécution. 

Une alternative consiste à passer un rappel.

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

Ce qui vous permettrait de l'utiliser comme tel.

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

J'espère que ça aide!

Edit: Ce qui précède suppose que vous travaillez dans un fichier JavaScript séparé que vous importerez ultérieurement dans votre fichier QML. Pour faire l'équivalent dans un fichier QML directement, vous pouvez le faire.

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
        })
    }
}

Je ne suis cependant pas convaincu que ce soit la solution à votre problème actuel; pour retarder une animation, vous pouvez utiliser PauseAnimation .

27
Marcus Ottosson

La réponse de Marcus fait le travail, mais il y a un gros problème .

Le problème est que le rappel reste connecté au signal triggered même après avoir été déclenché une fois. Cela signifie que si vous utilisez à nouveau cette fonction de délai, la minuterie déclenchera les rappels tous connectés avant. Vous devez donc déconnecter le rappel après avoir été déclenché.

Voici ma version améliorée de la fonction delay:

Timer {
    id: timer
    function setTimeout(cb, delayTime) {
        timer.interval = delayTime;
        timer.repeat = false;
        timer.triggered.connect(cb);
        timer.triggered.connect(function release () {
            timer.triggered.disconnect(cb); // This is important
            timer.triggered.disconnect(release); // This is important as well
        });
        timer.start();
    }
}

...

timer.setTimeout(function(){ console.log("triggered"); }, 1000);
6
Bumsik Kim

vous pouvez utiliser QtTest 

import QtTest 1.0
import QtQuick 2.9

ApplicationWindow{
    id: window

    TestEvent {
        id: test
    }

    function delay_ms(delay_time) {
        test.mouseClick(window, 0, 0, Qt.NoButton, Qt.NoModifier, delay_time)
    }
}
0
fcying