Подтвердить что ты не робот

Как создать функцию задержки в QML?

Я хотел бы создать функцию задержки в javascript, которая принимает параметр количества времени на задержку, поэтому я мог бы использовать его, чтобы ввести задержку между выполнением строк javascript в моем приложении QML. Возможно, это будет выглядеть так:

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

Мне нужно тело функции delay(). Обратите внимание, что setTimeout() javascript не работает в QML.

4b9b3361

Ответ 1

Как было предложено в комментариях к вашему вопросу, компонент Timer является хорошим решением.

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

Выше было бы так, как я его сейчас использую, и вот как я мог бы применить этот пример в вашем вопросе.

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

(что ничего не делает, читайте дальше)

Хотя точный способ, которым вы его реализуете, предполагает, что вы ищете его для блокировки до следующей строки вашей программы. Но это не очень хороший способ сделать это, так как это также блокирует все остальное в вашей программе, поскольку JavaScript работает только в одном потоке выполнения.

Альтернативой является передача обратного вызова.

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

Это позволит вам использовать его как таковое.

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

Надеюсь, что это поможет!

Изменить: Вышеупомянутое предполагает, что вы работаете в отдельном файле JavaScript, который позже импортируется в ваш файл QML. Чтобы сделать эквивалент в файле QML напрямую, вы можете сделать это.

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

Я не уверен, что это решение вашей реальной проблемы; для задержки анимации вы можете использовать PauseAnimation.

Ответ 2

Ответ Маркуса делает свою работу, но есть одна большая проблема.

Проблема в том, что обратный вызов остается подключенным к triggered сигналу даже после однократного срабатывания. Это означает, что если вы снова воспользуетесь этой функцией задержки, таймер снова вызовет все обратные вызовы, подключенные ранее. Поэтому вы должны отключить обратный вызов после срабатывания.

Это моя расширенная версия функции задержки:

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

Ответ 3

Здесь другой вариант, который использует объект Component для размещения объекта Timer.

Затем мы реализуем setTimeout на setTimeout функцию для динамического создания и вызова этого объекта Timer.

NB Ответ предполагает Qt5.12.x, который включает в себя ECMAScript 7 (и, следовательно, ECMAScript 6) для использования ярлыков параметров, параметров отдыха и синтаксиса разброса:

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

В следующем фрагменте мы будем вызывать console.log(31, 32, 33) с произвольной задержкой от 0 до 1000 мс.

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

Ответ 4

вы можете использовать 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)
    }
}