如何在QML中创建延迟函数?

问题描述 投票:0回答:7

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

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

我需要函数的主体

delay()
。请注意,JavaScript 的
setTimeout()
在 QML 中不起作用。

javascript qml delay
7个回答
48
投票

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


21
投票
有一个大问题

问题在于,即使触发一次,回调仍会保持与

triggered

信号的连接。这意味着如果您再次使用该延迟函数,计时器将再次触发之前连接的

all
回调。所以触发后应该断开回调。 这是我的增强版延迟功能:

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



4
投票
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-1000 毫秒之间的随机时间延迟调用 
console.log(31)

console.log(32)
console.log(33)

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

另请参阅:

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


1
投票

在需要时添加计时器的 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'); }



1
投票
https://stackoverflow.com/a/62051450/3220983

https://stackoverflow.com/a/50224584/3220983... 将此文件/组件添加到您的项目中:

调度程序.qml

import QtQuick 2.0 Timer { id: timer property var _cbFunc: null property int _asyncTimeout: 250 // Execute the callback asynchonously (ommiting a specific delay time) function async( cbFunc ) { delay( cbFunc, _asyncTimeout ) } // Start the timer and execute the provided callback ONCE after X ms function delay( cbFunc, milliseconds ) { _start( cbFunc, milliseconds, false ) } // Start the timer and execute the provided callback repeatedly every X ms function periodic( cbFunc, milliseconds ) { _start( cbFunc, milliseconds, true ) } function _start( cbFunc, milliseconds, isRepeat ) { if( cbFunc === null ) return cancel() _cbFunc = cbFunc timer.interval = milliseconds timer.repeat = isRepeat timer.triggered.connect( cbFunc ) timer.start() } // Stop the timer and unregister the cbFunc function cancel() { if( _cbFunc === null ) return timer.stop() timer.triggered.disconnect( _cbFunc ) _cbFunc = null } }

然后,在另一个组件中实现,例如:

... Scheduler { id: scheduler; } scheduler.delay( function(){ console.log('Delayed'); }, 3000 );

您可以使用此处所示的匿名函数,或者回调到命名函数。如果您不太关心确切的时间,请使用简单的 
async

以非阻塞方式触发代码。请注意,虽然对“异步”回调使用 0 毫秒超时很诱人(就像使用 C++ QTimer 一样),但这对于 QML Timer 来说并不是正确的方法!这些计时器似乎不会在优先考虑屏幕重绘的事件循环中对事件进行排队。因此,如果您的目标是推迟给定操作以首先实现“即时”UI 更改,则需要调高延迟间隔,如下所示。 使用 0ms 通常会导致代码在重绘之前触发。

请注意,这些“调度程序”实例之一只能在一个给定的时间间隔内绑定到一个回调函数。  如果您需要“重叠”延迟事件,则需要多个实例。


1
投票

void QmlUtils::singleShot(int msec, QJSValue callback) { QTimer::singleShot(msec, this, [callback] () mutable { if (callback.isCallable()) callback.call(); }); }

然后在 QML 中调用它,无论您身在何处:

qmlUtils.singleShot(5000, () => console.log("Hello!"))

完成。

如果需要,您可以使用

this

,甚至无需编写它。只需将其暴露给 QML: ctx->setContextProperty("lqtUtils", new lqt::QmlUtils(qApp));



0
投票

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

	
© www.soinside.com 2019 - 2024. All rights reserved.