webentwicklung-frage-antwort-db.com.de

Wie erstelle ich eine Verzögerungsfunktion in QML?

Ich möchte eine Verzögerungsfunktion in Javascript erstellen, die einen Verzögerungsparameter benötigt, sodass ich sie verwenden kann, um eine Verzögerung zwischen der Ausführung von JavaScript-Zeilen in meiner QML-Anwendung einzuführen. Es würde vielleicht so aussehen:

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

Ich brauche den Körper der Funktion delay(). Beachten Sie, dass setTimeout() of javascript in QML nicht funktioniert.

17

Wie in den Kommentaren zu Ihrer Frage vorgeschlagen, ist die Komponente Timer eine gute Lösung dafür.

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

Das obige wäre, wie ich es derzeit verwende, und hier ist, wie ich das Beispiel in Ihre Frage implementiert haben könnte.

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

(Was nichts tut; weiterlesen)

Die genaue Art und Weise, wie Sie die Implementierung suchen, deutet darauf hin, dass Sie block suchen, bis die nächste Zeile Ihres Programms ausgeführt wird. Dies ist jedoch kein sehr guter Weg, um darüber nachzudenken, da dies auch alles andere in Ihrem Programm blockieren würde, da JavaScript nur in einem einzigen Ausführungsthread ausgeführt wird. 

Eine Alternative besteht darin, einen Rückruf zu übergeben.

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

Damit könnten Sie es als solches verwenden.

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

Ich hoffe es hilft!

Bearbeiten: Bei den obigen Angaben wird davon ausgegangen, dass Sie in einer separaten JavaScript-Datei arbeiten, die Sie später in Ihre QML-Datei importieren. Um das Äquivalent in einer QML-Datei direkt auszuführen, können Sie dies tun.

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

Ich bin nicht überzeugt, dass dies die Lösung für Ihr aktuelles Problem ist. Um eine Animation zu verzögern, können Sie PauseAnimation verwenden.

27
Marcus Ottosson

Marcus 'Antwort erledigt den Job, aber es gibt ein großes Problem .

Das Problem ist, dass der Callback auch nach einmaliger Auslösung mit dem Signal triggered verbunden bleibt. Das heißt, wenn Sie diese Verzögerungsfunktion erneut verwenden, werden die zuvor verbundenen alle Rückrufe erneut ausgelöst. Sie sollten also nach dem Auslösen den Callback trennen.

Dies ist meine erweiterte Version der Verzögerungsfunktion:

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

Hier ist eine andere Variante, die das Objekt Component verwendet, um das Objekt Timer aufzunehmen.

Dann implementieren wir eine setTimeout -ähnliche Funktion, um dieses Timer -Objekt dynamisch zu erstellen und aufzurufen.

N.B. Die Antwort geht von Qt5.12.x aus, das ECMAScript 7 (und damit ECMAScript 6) enthält, um Parameterverknüpfungen, Ruheparameter und die Spread-Syntax zu verwenden:

    function setTimeout(func, interval, ...params) {
        return setTimeoutComponent.createObject(app, { func, interval, params})
    }

    function clearTimeout(timerObj) {
        timerObj.stop()
        timerObj.destroy()
    }

    Component {
        id: setTimeoutComponent
        Timer {
            property var func
            property var params
            running: true
            repeat: false
            onTriggered: {
                func(...params)
                destroy()
            }
        }
    }

Im folgenden Snippet rufen wir console.log(31, 32, 33) mit einer zufälligen Zeitverzögerung zwischen 0 und 1000 ms auf.

console.log("Started")
setTimeout(console.log, Math.floor(1000 * Math.random()), 31, 32, 33)

Siehe auch: https://community.esri.com/groups/appstudio/blog/2019/05/22/ecmascript-7-settimeout-and-arrow-functions

1
Stephen Quan

sie können QtTest verwenden 

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