Me gustaría crear una función de retraso en javascript que tome un parámetro de cantidad de tiempo para retrasar, de modo que pueda usarlo para introducir retrasos entre la ejecución de líneas de JavaScript en mi aplicación QML. Tal vez se vería así:
function delay(delayTime) { // code to create delay } Necesito el cuerpo de la función delay() . Tenga en cuenta que setTimeout() de JavaScript no funciona en QML.
Como se sugiere en los comentarios a su pregunta, el componente Timer es una buena solución para esto.
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();Lo anterior sería cómo lo estoy usando actualmente, y así es como podría haber implementado el ejemplo en su pregunta.
function delay(delayTime) { timer = new Timer(); timer.interval = delayTime; timer.repeat = false; timer.start(); }(Que no hace nada; sigue leyendo)
Aunque la forma exacta en que está buscando que se implemente sugiere que está buscando que se bloquee hasta que se ejecute la siguiente línea de su programa. Pero esta no es una muy buena manera de hacerlo, ya que también bloquearía todo lo demás en su programa, ya que JavaScript solo se ejecuta en un solo hilo de ejecución.
Una alternativa es pasar una devolución de llamada.
function delay(delayTime, cb) { timer = new Timer(); timer.interval = delayTime; timer.repeat = false; timer.triggered.connect(cb); timer.start(); }Lo que te permitiría usarlo como tal.
delay(1000, function() { print("I am called one second after I was started."); });¡Espero eso ayude!
Editar: lo anterior supone que está trabajando en un archivo JavaScript separado que luego importa a su archivo QML. Para hacer el equivalente en un archivo QML directamente, puede hacer esto.
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 }) } }Sin embargo, no estoy convencido de que esta sea la solución a su problema real; para retrasar una animación, puede usar PauseAnimation .
La respuesta de Marcus hace el trabajo, pero hay un gran problema .
El problema es que la devolución de llamada se mantiene conectada a la señal triggered incluso después de activarse una vez. Esto significa que si usa esa función de retraso nuevamente, el temporizador activará todas las devoluciones de llamada conectadas antes nuevamente. Por lo tanto, debe desconectar la devolución de llamada después de que se active.
Esta es mi versión mejorada de la función de retraso:
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);Aquí hay otra variación que utiliza el objeto Component para albergar el objeto Timer .
Luego implementamos una función similar a setTimeout para crear e invocar dinámicamente este objeto Timer .
NB La respuesta asume Qt5.12.x que incluye ECMAScript 7 (y por lo tanto ECMAScript 6) para utilizar atajos de parámetros, parámetros de descanso y sintaxis extendida:
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(); } } } En el siguiente fragmento, console.log(31) , console.log(32) , console.log(33) en un retraso de tiempo aleatorio entre 0 y 1000 ms a partir de ahora.
console.log("Started"); setTimeout(console.log, Math.floor(1000 * Math.random()), 31); setTimeout(console.log, Math.floor(1000 * Math.random()), 32); setTimeout(console.log, Math.floor(1000 * Math.random()), 33);Consulte también: https://community.esri.com/groups/appstudio/blog/2019/05/22/ecmascript-7-settimeout-and-arrow-functions