Что является эквивалентом setTimeout JavaScript на qtScript?
Не так много, чтобы добавить; что эквивалентно setTimeout JavaScript на qtScript?
4 ответа
Вот как вы можете расширить свой язык сценариев, предоставив автономный метод C++ (нет необходимости вести учет идентификаторов таймера или около того). Просто создайте следующий слот с именем "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()));
}
И представьте этот слот как функцию для глобального объекта вашего скриптового движка. Это можно сделать разными способами, например, просто создав функцию QScriptValue через экземпляр QScriptEngine и установив свойство с соответствующим именем в существующем глобальном объекте движка. В моем случае, однако, весь экземпляр ScriptGlobalObject устанавливается как новый глобальный объект, например так:
mScriptGlobalObject = new ScriptGlobalObject(this);
engine->setGlobalObject(engine->newQObject(mScriptGlobalObject));
Обратите внимание, что если вы хотите использовать "context()", как показано в приведенном выше коде setTimeout, ваш ScriptGlobalObject должен также быть производным от QScriptable, например так:
class ScriptGlobalObject : public QObject, protected QScriptable
В этом сценарии вы можете теперь использовать setTimeout, чтобы вызвать метод позднее (до тех пор, пока экземпляр QScriptEngine, из которого он происходит, не будет удален):
setTimeout(function() {
// do something in three seconds
}, 3000);
Вы можете выставить QTimer
в качестве экземпляра класса для механизма сценариев. Затем вы можете создать его с помощью new QTimer()
,
Это задокументировано в разделе Создание приложений с возможностью написания скриптов
Ниже приведен полный пример. Таймер срабатывает через секунду после оценки скрипта, печатает timeout
на консоли и выходит из приложения.
// https://github.com/KubaO/stackrun/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();
}
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 предоставляет пример в проекте context2d, как получить доступ к функциям setInterval/clearInterval setTimeout/clearTimeout из сценария.
В классе 'Environment' этого проекта функция startTimer объекта QObject вызывается каждый раз, когда сценарий вызывает setInterval/setTimeout. Затем идентификатор таймера добавляется в QHash со ссылкой на обратный вызов javascript. Когда обратный отсчет таймера (часть C++) закончен, вызывается timerEvent класса 'Environment', а затем вызывается обратный вызов javascript..
Обратите внимание, что все таймеры уничтожаются в Environment::reset() для очистки контекста.
см.: https://doc.qt.io/archives/qt-4.7/script-context2d.html
Вот моя заявка на "Кладж года"... но это работает И не требует перекомпиляции серверной части 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 Script):
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!");
}
Наконец, где возможно, запустите свой "таймер" с помощью основного трюка, используя функцию "animateClick" QPushButton:
var page = gui.pageWidgetByObjectName("DynamicMyTimerKludgePage");
page.timerKludgeButton.animateClick(2000);