如何在QML中创建延迟功能?

时间:2015-02-13 19:49:54

标签: javascript qml delay

我想在javascript中创建一个延迟函数,它接受延迟的时间量参数,这样我就可以使用它在我的QML应用程序中执行javascript行之间引入延迟。它可能看起来像这样:

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

我需要函数delay()的主体。请注意,setTimeout()的javascript在QML中不起作用。

5 个答案:

答案 0 :(得分:31)

正如您对问题的评论中所建议的,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

答案 1 :(得分:8)

马库斯'答案可以胜任,但有一个大问题

问题是,即使在触发一次后,回调也会保持与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);

答案 2 :(得分:1)

这是另一个利用Component对象容纳Timer对象的变体。

然后,我们实现一个类似setTimeout的函数来动态创建和调用此Timer对象。

答案假定为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()
            }
        }
    }

在以下代码段中,我们将从现在开始的0-1000ms之间的随机时间延迟中调用console.log(31, 32, 33)

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

另请参阅:https://community.esri.com/groups/appstudio/blog/2019/05/22/ecmascript-7-settimeout-and-arrow-functions

答案 3 :(得分:0)

你可以使用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)
    }
}

答案 4 :(得分:0)

来自Bumsik Kim的答案很棒,该答案对其进行了细微的更改,以便可以重复使用计时器,然后在需要时将其停止并重新使用。

要在需要的地方添加计时器的QML。

// Allow outside access (optional)
property alias timer: timer

Timer {
    id: timer

    // Start the timer and execute the provided callback on every X milliseconds
    function startTimer(callback, milliseconds) {
        timer.interval = milliseconds;
        timer.repeat = true;
        timer.triggered.connect(callback);
        timer.start();
    }

    // Stop the timer and unregister the callback
    function stopTimer(callback) {
        timer.stop();
        timer.triggered.disconnect(callback);
    }
}

可以按如下使用。

timer.startTimer(Foo, 1000); // Run Foo every 1 second
timer.stopTimer(Foo); // Stop running Foo

timer.startTimer(Bar, 2000); // Run Bar every 2 seconds
timer.stopTimer(Bar); // Stop running Bar

function Foo() {
    console.log('Executed Foo');
}

function Bar() {
    console.log('Executed Bar');
}