Использование QThread с сигналом / слотами в контексте QML - PullRequest
0 голосов
/ 12 декабря 2018

Пожалуйста, посмотрите на следующий (рабочий) пример.

Мой вопрос довольно прост:

  • Правильно ли я использую QThread в связи с контекстом Qml?
  • Это безопасный способ связи с Qml с QThread и наоборот?

Если WorkerThread расширен для выполнения какой-либо тяжелой работы или выполнения чего-либо, что может блокировать, я хочуубедитесь, что мой пользовательский интерфейс ни в коем случае не зависает.

main.qml

import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.0

Window {
    id: window
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    Connections {
        target: window.visible ? _qWorkerThreadController : null

        onResponseToQml: {
            t.text = response;
        }
    }

    Timer {
        id: timer
        interval: 1000
        repeat: false
        triggeredOnStart: false

        onTriggered: {
            _qWorkerThreadController.methodCallQml("test");
        }
    }

    Rectangle {
        width: 200
        height: 200
        color: "green"
        anchors.centerIn: parent
        Label {
            id: t
            color: "red"
            height: 20
            width: 50
            anchors.centerIn: parent
        }
    }

    Component.onCompleted: {
        timer.start();
    }
}

workerthread.cpp

#include "workerthread.h"


WorkerThread::WorkerThread(QObject *parent) :
    QObject(parent)
{

}

void WorkerThread::methodCallSlot(QString s) {
    // do Some work with 's'
    QMetaObject::invokeMethod(this->m_caller, "methodCallQmlResponse", Qt::QueuedConnection, Q_ARG(QString, s));
}

void WorkerThread::setCaller(QObject *caller) {
    this->m_caller = caller;
}

workerthreadcontroller.cpp

#include "workerthreadcontroller.h"
#include "workerthread.h"

#include <QThread>
#include <QDebug>

WorkerThreadController::WorkerThreadController(QObject *parent) :
    QObject(parent)
{
    WorkerThread *worker = new WorkerThread();
    this->m_workerThread = worker;
    QThread *t = new QThread();
    worker->moveToThread(t);
    connect(t, &QThread::finished, t, &QThread::deleteLater);
    connect(t, &QThread::started, this, [=]() { m_workerThread->setCaller(this);});
    connect(m_workerThread, &WorkerThread::methodCallSignal, m_workerThread, &WorkerThread::methodCallSlot);
    t->start();
}

void WorkerThreadController::methodCallQml(QString s) {
    qDebug() << s;
    emit m_workerThread->methodCallSignal(s);
}

void WorkerThreadController::methodCallQmlResponse(QString s) {
    emit responseToQml(s);
}

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "workerthreadcontroller.h"

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

    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;

    WorkerThreadController workerThreadController;
    engine.rootContext()->setContextProperty("_qWorkerThreadController", &workerThreadController);
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}
...