【问题标题】:What is the equivalent of JavaScript's setTimeout on qtScript?qtScript 上 JavaScript 的 setTimeout 等价物是什么?
【发布时间】:2012-06-28 01:29:32
【问题描述】:

没有太多要补充的; qtScript 上 JavaScript 的 setTimeout 等价物是什么?

【问题讨论】:

标签: javascript timer settimeout qtscript


【解决方案1】:

通过提供自包含的 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】:

    您可以将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();
    }
    

    【讨论】:

      【解决方案3】:

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

      注意任何错误,我只是在这里编码。

      【讨论】:

      • 谢谢,但我觉得奇怪的是 Qt 的人没有让它变得更友好.. 提供 setTimeout/setInterval 对我来说似乎很容易。
      • @RushPL 是的,这对于一些有 JS 或 NodeJS 背景的人来说会很棒,但我认为他们希望 API 更像普通的 C++ QT。
      • 在 Qt 中为 Node.JS API 提供某种 shim 会很酷 :)
      • 我收到一个错误:ReferenceError: Can't find variable: QTimer
      • 这个答案不完整。 Qt 脚本引擎对QTimer 一无所知,它也没有console 函数。
      【解决方案4】:

      Qt 在“context2d”项目中提供了一个示例,可以通过脚本访问 setInterval/clearInterval setTimeout/clearTimeout 功能。

      在本项目的“Environment”类中,每次脚本调用 setInterval/setTimeout 时都会调用 QObject 的 startTimer 函数。 然后将计时器标识符添加到 QHash 中,并带有对 javascript 回调的引用。 当定时器(c++部分)倒计时结束时,调用'Environment'类的timerEvent,然后调用javascript回调..

      请注意,所有计时器都在 Environment::reset() 中被杀死,以便清理上下文。

      见:https://doc.qt.io/archives/qt-4.7/script-context2d.html

      【讨论】:

        【解决方案5】:

        这是我为“年度最佳组合”提交的内容……但这有效,并且不需要重新编译 C++ 后端,因为涉及的工作量太大!我不确定你们其他人如何使用现在的 defunk Qt 脚本,但我需要 Qt 安装程序框架,我想开箱即用 - 而不是通过整个工具集的自定义分支,供我尝试维护(因为 QtIFW 本身仍在积极更新中),或者必须移植,在其他平台上编译,与合作者共享......

        那么我的解决方案是什么?好吧,没有QTimer 暴露给标准脚本引擎,但是您可以定义自己的自定义(即“动态”)安装程序向导页面,通过 Qt 表单(.ui 文件)定义接口。有了它,您可以放入任何 QWidget,然后在 Qt 脚本端为信号和插槽添加连接......所以,我只使用了我看到的第一组,也许是最简单的小部件信号和插槽内置了某种计时器机制,我可以利用它。

        在自定义表单中,将其放在某处,添加一个隐藏的 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);
        

        【讨论】:

          猜你喜欢
          • 2014-12-06
          • 2012-02-05
          • 2014-07-27
          • 2017-12-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-09-21
          相关资源
          最近更新 更多