停止评估Qt脚本

时间:2014-01-08 09:24:13

标签: c++ qt qtscript

我最近在模拟器上添加了一个脚本函数。我在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()插槽,但它只适用于事件循环。是否有现成的插槽或痘痘技巧?

感谢。

2 个答案:

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