添加量不大;在qtScript上,JavaScript的setTimeout相当于什么?
答案 0 :(得分:3)
您可以将QTimer
作为可实例化的类公开给脚本引擎。然后,您可以通过new QTimer()
实例化它。
Making Applications Scriptable中记录了这一点。
下面是一个完整的例子。在评估脚本后,计时器将触发一秒钟,在控制台上打印timeout
,然后退出应用程序。
// https://github.com/KubaO/stackoverflown/tree/master/questions/script-timer-11236970
#include <QtScript>
template <typename T> void addType(QScriptEngine * engine) {
auto constructor = engine->newFunction([](QScriptContext*, QScriptEngine* engine){
return engine->newQObject(new T());
});
auto value = engine->newQMetaObject(&T::staticMetaObject, constructor);
engine->globalObject().setProperty(T::staticMetaObject.className(), value);
}
int main(int argc, char ** argv) {
QCoreApplication app{argc, argv};
QScriptEngine engine;
addType<QTimer>(&engine);
engine.globalObject().setProperty("qApp", engine.newQObject(&app));
auto script =
"var timer = new QTimer(); \n"
"timer.interval = 1000; \n"
"timer.singleShot = true; \n"
"var conn = timer.timeout.connect(function(){ \n"
" print(\"timeout\"); \n"
" qApp.quit(); \n"
"}); \n"
"timer.start();\n";
engine.evaluate(script);
return app.exec();
}
答案 1 :(得分:3)
通过提供一个独立的C ++方法(无需记录计时器ID等),您可以通过以下方式扩展脚本语言。只需创建名为“setTimeout”的以下插槽:
void ScriptGlobalObject::setTimeout(QScriptValue fn, int milliseconds)
{
if (fn.isFunction())
{
QTimer *timer = new QTimer(0);
qScriptConnect(timer, SIGNAL(timeout()), QScriptValue(), fn);
connect(timer, SIGNAL(timeout()), timer, SLOT(deleteLater()));
timer->setSingleShot(true);
timer->start(milliseconds);
} else
context()->throwError(tr("Passed parameter '%1' is not a function.").arg(fn.toString()));
}
并将该插槽作为函数引入脚本引擎的全局对象。这可以以不同的方式完成,例如,只需通过QScriptEngine实例创建一个QScriptValue函数,并在引擎的现有全局对象上设置相应的命名属性。但是,在我的情况下,整个ScriptGlobalObject实例被设置为新的全局对象,如下所示:
mScriptGlobalObject = new ScriptGlobalObject(this);
engine->setGlobalObject(engine->newQObject(mScriptGlobalObject));
请注意,如果您想使用上面的setTimeout代码中显示的“context()”,您的ScriptGlobalObject也应该从QScriptable派生,如下所示:
class ScriptGlobalObject : public QObject, protected QScriptable
在脚本中,您现在可以使用setTimeout来调用稍后调用的方法(只要在此期间不会删除它所源自的QScriptEngine实例):
setTimeout(function() {
// do something in three seconds
}, 3000);
答案 2 :(得分:2)
setTimeout和setInterval未在ECMAScript规范中定义,因为它们不是JavaScript功能。这些功能是浏览器环境的一部分。所以,QTscript没有它们。
您可以使用QTimer来实现此功能。 这是一个如何在QTScript中使用它的快速代码。
var timer = new QTimer();
timer.interval = 100; // set the time in milliseconds
timer.singleShot = true; // in-case if setTimout and false in-case of setInterval
timer.timeout.connect(this, function(){console("in setTimout")});
timer.start();
注意任何错误,我只是在这里编码。
答案 3 :(得分:2)
Qt在'context2d'项目中提供了一种从脚本访问setInterval / clearInterval setTimeout / clearTimeout功能的方法。
在这个项目的'Environment'类中,每次脚本调用setInterval / setTimeout时都会调用QObject的startTimer函数。 然后在QHash中添加计时器标识符,其中包含对javascript回调的引用。 当计时器(c ++部分)的倒计时结束时,调用'Environment'类的timerEvent,然后调用javascript回调..
请注意,所有计时器都在Environment :: reset()中被杀死,以便清理上下文。
答案 4 :(得分:0)
这是我提交的“年度最佳歌曲” ...,但是这种方法有效,并且不需要重新编译C ++后端,因为这涉及太多的工作!我不确定其他人可能如何使用现在已失效的Qt脚本,但是我需要的是 Qt Installer Framework ,我想直接使用它-而不是通过整个工具集的自定义分支,然后让我尝试维护(因为QtIFW本身仍在积极更新),或者不得不移植,在其他平台上进行编译,与合作者共享...
那我的解决方案是什么?嗯,没有QTimer
公开给标准脚本引擎,但是您可以定义自己的自定义(即“动态”)安装程序向导页面,并通过Qt表单(.ui文件)定义界面。这样,您可以放入任何QWidget,然后在Qt Script端添加信号和插槽的连接...因此,我只使用了我看到的第一个(也许是最简单的)一组窗口信号和插槽有某种内置的计时器机制,我可以利用。
在自定义表单中,将其放置在某处,添加隐藏的QPushButton :
<widget class="QPushButton" name="timerKludgeButton">
<property name="visible">
<bool>false</bool>
</property>
</widget>
然后,当您加载包含.ui(窗体)的组件时,请将按钮的“已释放”信号连接到自定义的“插槽”(即Qt脚本功能):
Component.prototype.componentLoaded = function(){
var page = gui.pageWidgetByObjectName("DynamicMyTimerKludgePage");
page.timerKludgeButton.released.connect(this, this.onTimeOut);
}
接下来,定义插槽:
Component.prototype.onTimeOut = function(){
console.log("Asynchronous time out!");
}
最后,在适当的地方,使用QPushButton的“ animateClick” 函数以此处的核心技巧启动“计时器”:
var page = gui.pageWidgetByObjectName("DynamicMyTimerKludgePage");
page.timerKludgeButton.animateClick(2000);