2017-03-05 63 views
3

我有兩個JavaScript函數fun1fun2在QML,並要執行一個(fun2)陸續(fun1)結束後,更確切地說,我怎麼在fun1ImageReader完成後開始fun2()ImageReader是通過繼承QImageProvider用C++編寫的函數,如下所示:的Javascript等待QML

function fun1(){ 
    ImageReader.magic(photo); 
} 
function fun2(){ 
    myImg.source = ""; 
    myImg.source = "image://ImageReader"; 
} 
fun1(); 
fun2(); 

的使用情況是,我要處理在C++中的圖像,並且當該處理完成時,通過QML圖片項目顯示它。

+1

那麼你的問題是什麼?你不是已經根據你提供的代碼在'func1()'之後執行'func2()'嗎? – folibis

+0

我會建議一個接一個地打電話給他們。例如像代碼[這裏](http://stackoverflow.com/questions/42607709/javascript-waiting-in-qml)。是什麼讓你覺得他們不是一個接一個地被執行? – derM

+0

我認爲你的問題是,'fun1()'只啓動在另一個線程中異步執行的ImageReader.magic(photo)方法。所以你的問題應該是:*在'ImageReader'完成他的魔法之後,我該如何開始'fun2()',因爲'fun1()'可能在此之前完成。所以'fun2()'在'fun1()'完成之後,'ImageReader.magic(photo)'完成之前執行。 – derM

回答

3

基本上你對如何處理這個

  1. 使異步處理兩個選項通知它正在完成
  2. 投票結果的可用性

我不會推薦第二種方法,特別是在聲明式環境中,所以讓我們進一步研究選項之一。

對於C++和QML/JavaScript的,你再有通知基本上有兩種選擇

  1. 使用QObject信號機制
  2. 傳遞一個JavaScript回調到C++,並調用從那裏

Qt的asnychronous QML API通常與前者一起完成,但如果您更喜歡後者,請查看QJSValue作爲用於回調參數的C++數據類型。

0

我不太瞭解QML,我認爲在普通JavaScript中你的代碼應該可以工作。但我可以,如果建議你這個醜陋的方式它沒有要求順序:

function fun1() { 
    ImageReader.magic(photo); 
    return 1; 
} 
function fun2(wait){ 
    if(wait==1) 
    { 
     myImg.source = ""; 
     myImg.source = "image://ImageReader"; 
    } 
} 
fun2(fun1()); 
+0

謝謝。但它仍然不起作用。 'ImageReader.magic(photo);'是通過繼承QImageProvider用C++編寫的函數,它需要較長的時間來處理圖像並返回QML。 – zzj

5

好吧,我只想爲那些將要搜索相同解決方案的人進行總結。

至少有2種方式來做到這一點:

  • 從C++對象引發一個信號,當任務完成。
  • 將JS函數傳遞給C++,任務完成後將調用它。

測試C++對象聲明:

class MyItem : public QObject 
{ 
    Q_OBJECT 

public: 
    MyItem(QObject *parent = 0); 
    Q_INVOKABLE void someAsyncFunc(); 
    Q_INVOKABLE void someAnotherAsyncFunc(QJSValue value); 

signals: 
    void someAsyncFuncFinished(); 
}; 

測試C++對象實現:

MyItem::MyItem(QObject *parent) : 
QObject(parent) {} 

void MyItem::someAsyncFunc() 
{ 
    // do some work here 
    emit someAsyncFuncFinished(); 
} 

void MyItem::someAnotherAsyncFunc(QJSValue value) { 
    // do some work here 
    if (value.isCallable()) { 
     value.call(); 
    } 
} 

註冊自定義項作爲單:

static QObject *my_singleton_provider(QQmlEngine *engine, QJSEngine *scriptEngine) 
{ 
    Q_UNUSED(engine) 
    Q_UNUSED(scriptEngine) 
    static MyItem *item = nullptr; 
    if(!item) 
     item = new MyItem(); 
    return item; 
} 

int main(int argc, char *argv[]) 
{ 
    QApplication app(argc, argv); 

    qmlRegisterSingletonType<MyItem>("Qt.MyTest", 1, 0, "MyItem", my_singleton_provider); 

    QQmlApplicationEngine engine; 
    engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); 
    return app.exec(); 
} 

所以QML文件來測試它:

1.信號發射時完成任務

Item { 
    id: testItem 

    function func1() 
    { 
     console.log("func1 executing...") 
     MyItem.someAsyncFuncFinished.connect(func2); 
     MyItem.someAsyncFunc(); 
    } 

    function func2() 
    { 
     console.log("func2 executing...") 
    } 

    Component.onCompleted: func1(); 
} 

2. JS傳遞函數C++:

Item { 
    id: testItem 

    function func1() 
    { 
     console.log("func1 executing...") 
     MyItem.someAnotherAsyncFunc(func2); 
    } 

    function func2() 
    { 
     console.log("func2 executing...") 
    } 

    Component.onCompleted: func1(); 
}