Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript waiting in QML

Tags:

qt5

qml

I have two javascript functions fun1, fun2 in QML, and want to execute one (fun2) after another (fun1) is finished, more precisely, how do I start fun2() after the ImageReader in fun1 is done. ImageReader is a function written in C++ by inheriting QImageProvider, as follows:

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

The usage scenario is that I want to process an image in C++, and when the processing is done, show it by QML Image item.

like image 994
Zhenjie Zhao Avatar asked Feb 05 '23 23:02

Zhenjie Zhao


1 Answers

Ok, I just want to summarize for those who will search for the same solution.

There are at least 2 ways to do that:

  • Emit signal from C++ object when task done.
  • Pass JS function to C++ which will be called when task done.

Test C++ object declaration:

class MyItem : public QObject
{
    Q_OBJECT

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

signals:
    void someAsyncFuncFinished();
};

Test C++ object implementation:

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

Registering custom item as a singleton:

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

And so QML files to test it:

1. Signal fired when task finished

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. Passing JS function to C++:

Item {
    id: testItem

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

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

    Component.onCompleted: func1();
}
like image 126
folibis Avatar answered Feb 08 '23 17:02

folibis