如何在 QML 函数异步的同时使用 QML 中的 QThread

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

我正在寻找在 QML 中使用 QThread 的方法。 我想将参数传递给 QThread 函数并从中 return 一个 bool 值。

我想从 QML 方面做的另一件事是,当应用程序执行将在 calling/executing QThread.

之前发生的脚本时,不要阻止应用程序

下面是一个示例代码:

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
}

如何做到这些?

正确注册类型:

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

在 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

    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
                        }
                    }
 ....
}

您犯了几个错误,导致您偏离预期。

正如@folibis 和@Hubi 已经提到的那样——您使用了以小写字母开头的 C++ class 名称。 QML 有问题。


关于multi-threading,有很多方法可以做到。这实际上取决于您的特定任务。

我真的建议你阅读下一篇文章(来自官方 Qt 文档):

由于您在 Qt 和 QML 中有信号,您可以在 C++ 中实现您想要的所有内容,然后将其放到 QML 中。

你可以参考这个simple project on GitHub我已经为你准备好了。实施了 moveToThread 方法。