2014-01-08 141 views
3

我最近在模擬器上添加了一個腳本函數。我在GUI上添加了一個「啓動腳本」按鈕,他可以啓動對腳本的評估。停止評估Qt腳本

我的主創建一個QThread(scriptThread)誰評估我的腳本。我的QMainWindows發送信號給我的main,誰調用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())); 

這是我的run()函數在我scriptThread:

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()插槽,但它僅適用於事件循環。有沒有現有的插槽或小伎倆來做到這一點?

謝謝。

+1

你使用的是什麼版本的Qt?在Qt 4.4中有abortEvaluation成員添加到QScriptEngine –

+0

我在Qt 4.8.1上,謝謝,我會試試看。 – MokaT

回答

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

abortEvaluation()沒有按」 t爲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!"); 
} 

當然,腳本可以捕獲該異常並繼續,有它贏得了非常好的機會不過,即使這樣做,它也有可能擺脫無限循環。