追加することはあまりありません。qtScript の JavaScript の setTimeout に相当するものは何ですか?
5 に答える
自己完結型の 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);
QTimer
をインスタンス化可能なクラスとしてスクリプト エンジンに公開できます。その後、 を介してインスタンス化できますnew QTimer()
。
これはMaking Applications Scriptableに記載されています。
以下は完全な例です。タイマーは、スクリプトが評価されてから 1 秒後に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();
}
Qt は、「context2d」プロジェクトで、スクリプトから setInterval/clearInterval setTimeout/clearTimeout 機能にアクセスする方法の例を提供します。
このプロジェクトの「環境」クラスでは、スクリプトが setInterval/setTimeout を呼び出すたびに QObject の startTimer 関数が呼び出されます。次に、タイマー識別子が QHash に追加され、javascript コールバックが参照されます。タイマー(C++部分)のカウントダウンが終わると、「Environment」クラスのtimerEventが呼び出され、その後javascriptコールバックが呼び出されます。
コンテキストを消去するために、すべてのタイマーが Environment::reset() で強制終了されることに注意してください。
setTimeout と setInterval は JavaScript の機能ではないため、ECMAScript 仕様では定義されていません。これらの機能はブラウザ環境の一部です。したがって、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();
バグに注意してください。ここでコーディングしました。
これが私の "kludge of the year" への提出物です... しかし、これは機能し、C++ バックエンドを再コンパイルする必要はありません。残りの皆さんが現在は機能していない Qt Script をどのように使用しているかはわかりませんが、私は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);