Nmaster88
Nmaster88

Reputation: 1585

How to use QThread from QML while having QML function async too

I'm looking for the way to use QThread in QML. I want to pass parameters to the QThread function and return a bool value from it.

Another thing I want from the QML side is to not block the app when it's executing a script that will happen before calling/executing the QThread.

Below is an example code:

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "testasync.h"

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
    qmlRegisterType<testAsync>("testAsync",1,0,"thread");//not working on main.qml
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}

main.qml

import QtQuick 2.0
import QtQuick.Controls 1.4
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3
//import testAsync 1.0

ApplicationWindow {
    id: window
    title: "Stack"
    visible: true
    width: 1400

    Page {
        id: page
        anchors.fill: parent
        property int responsiveWidth: 1000
        property int maximumWidth: 900
        ScrollView {
            id:configScroll
            anchors.fill: parent
            GridLayout {
                columns: 2
                width: page.width > page.responsiveWidth ? page.maximumWidth : page.width
                anchors.top: parent.top
                anchors.left: parent.left
                anchors.leftMargin: page.width > page.responsiveWidth ? (page.width - childrenRect.width)/2 : 10
                anchors.rightMargin: page.width > page.responsiveWidth ? 0 : 10
                //this function needs to be processed and will return the values we need for the testasync. this can't block UI thread too
                function teste() {
                            for(var i=0; i<10000000; i++)
                            {
                                console.log(i)
                            }
                  return "teste"
                 }
                    Button {
                        property bool test: true
                        text: "async"
                        onClicked: {
                            var val = parent.teste()
//                            if(test)
//                                val=thread.start()
//                            else
//                                val=thread.quit()
                            console.log(val)
                            test=!test
                        }
                    }
            }
        }
    }
}

testasync.h

#ifndef TESTASYNC_H
#define TESTASYNC_H
#include <QThread>
#include <QObject>

class testAsync : public QThread
{
    Q_OBJECT
public:
    testAsync();
    void run();
private:
    QString name;
};
#endif // TESTASYNC_H

testasync.cpp

#include "testAsync.h"
#include <QDebug>
#include <QtCore>
testAsync::testAsync(){}

void testAsync::run() {
    for(int i = 0; i <= 100; i++)
    {
        qDebug() << this->name << " " << i;
    }
    //return true
}

How can these be done?

Upvotes: 1

Views: 2735

Answers (2)

NG_
NG_

Reputation: 7181

You've done several errors that drives you away from desired.

As it was already mentioned by @folibis and by @Hubi -- you've used C++ class names which starts from small letter. QML has problems with it.


Regarding multi-threading, there are a lots of ways to do it. It really depends on your particular tasks.

I do really recommend you to read next articles (from official Qt documentation):

Since you have signals in Qt and QML, you may implement all what you want in C++ and then just drop it to QML.

You may refer to this simple project on GitHub I've prepared for you. There is moveToThread approach implemented.

Upvotes: 1

Hubi
Hubi

Reputation: 1639

Register the type correctly:

qmlRegisterType<testAsync>("TestAsync", 1, 0, "TestAsync");

Make a instance of your type in the qml file and call the methods of it.

import QtQuick 2.0
import QtQuick.Controls 1.4
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3
import TestAsync 1.0

ApplicationWindow {
    id: window
    title: "Stack"
    visible: true
    width: 1400

    TestAsync {
        id: threadAsync
    }

    Page {
        ....
                    Button {
                        property bool test : true
                        text: "async"
                        onClicked: {
                            if(test) {
                                val=threadAsync.start()
                            } else {
                                val=threadAsync.quit()
                            }
                            console.log(val)
                            test=!test
                        }
                    }
 ....
}

Upvotes: 2

Related Questions