我最近在模拟器上添加了一个脚本函数。我在GUI上添加了一个“启动脚本”按钮,可以启动脚本评估。
我的主人创建了一个评估我的脚本的QThread(scriptThread)。我的QMainWindows向我的主人发送信号,他们调用了scriptThread插槽。
我希望能够启动,并在我想要GUI时停止脚本。我第一次调用了scriptThread的terminate()槽。但它破坏了我的Qthread,并且在取消它之后我无法重新删除脚本(因为我在我的主要开头创建了我的scriptThread)。
这是我主要的一部分:
MyGUI w();
ScriptThread scriptThread();
QObject::connect(&w, SIGNAL(setScriptPath(QString)),
&scriptThread, SLOT(setPath(QString)));
QObject::connect(&w, SIGNAL(launchScriptSignal()),
&scriptThread, SLOT(start()));
QObject::connect(&w, SIGNAL(stopScript()),
&scriptThread, SLOT(terminate()));
QObject::connect(&scriptThread, SIGNAL(finished()),
&w, SLOT(scriptFinished()));
这是我的scriptThread中的run()函数:
QScriptEngine m_scriptEngine;
QScriptValue m_result;
QScriptValue m_scriptValue = m_scriptEngine.newQObject(m_MyQOBJECT);
m_scriptEngine.globalObject().setProperty("sc", m_scriptValue);
QFile file(m_path);
bool result = file.open(QIODevice::ReadOnly);
if(!result)
{
printf("Script path not found.\n");
emit finished();
return;
}
m_result = m_scriptEngine.evaluate(file.readAll());
if(m_result.toString() != "undefined")
std::cout << m_result.toString().toStdString() << std::endl;
file.close();
if(m_scriptEngine.hasUncaughtException())
{
int lineNo = m_scriptEngine.uncaughtExceptionLineNumber();
printf("lineNo : %i\n", lineNo);
}
printf("ScriptThread finished\n");
emit finished();
GUI有趣的功能:
void myGUI::launchScript(QString path)
{
if(!m_isScriptRunning)
{
path = ui->editScriptPath->text();
disableAll();
ui->Script->setText("stop script");
m_isScriptRunning = true ;
emit setScriptPath(path);
emit launchScriptSignal();
}
else
{
emit stopScript();
scriptFinished();
}
}
void MyGUI::scriptFinished()
{
enableAll();
ui->Script->setText("launch script");
m_isScriptRunning = false ;
}
所以我的问题是,如何在不破坏线程的情况下取消对脚本的评估?我已经尝试过quit()插槽,但它只适用于事件循环。是否有现成的插槽或痘痘技巧?
感谢。
答案 0 :(得分:1)
abortEvaluation()
不适用于QScriptValue::call()
,也不适用于从C ++代码到javascript的调用。要中断这些,您可以抛出异常。这对我有用,我把它放在这里所以没有其他人不得不花时间去寻找它:
if(engine->isEvaluating())
{
engine->abortEvaluation();
}
else
{
QScriptContext *ctx = engine->currentContext();
if(ctx)
ctx->throwError("Code has been executing for too long!");
}
当然,脚本可以捕获这个异常并继续,但它很有可能赢了,即使它确实如此,它也可能会脱离无限循环。
答案 1 :(得分:0)
我成功地尝试了卡米尔解决方案。
在Qt 4.4及更高版本中,有一个QScriptEngine :: abortEvaluation()函数正常工作。
我只是将我的函数本地的引擎切换到我的班级。
ScriptThread.cpp的工作部分代码:
void ScriptThread::cancelScriptEvaluation()
{
m_scriptEngine.abortEvaluation();
emit finished();
}
当然在ScriptThread.h中:
private:
QScriptEngine m_scriptEngine;
在我的主要内容中:
QObject::connect(&w, SIGNAL(stopScript()),
&scriptThread, SLOT(cancelScriptEvaluation()));