QML中的线程渲染器

Threaded renderer in QML

本文关键字:线程 QML      更新时间:2023-10-16

线程化渲染器在以下代码中不起作用。我使用的是Arch linux-3.14上的Qt 5.4和专有驱动器。

----------mytext.h---------------

#include <QObject>
class Thing : public QObject {
    Q_OBJECT
    Q_PROPERTY(int qm_no READ qm_no  NOTIFY qm_noChanged)
public:
    Q_INVOKABLE void loop();
    int qm_no();
signals:
    void qm_noChanged();
private:
    int m_no;
};

----------mytext.cpp---------------

#include "mytext.h"
#include <unistd.h>
int Thing::qm_no() {
    return m_no;
}
void Thing::loop() {
    while(true) {
        m_no += 1;
        emit qm_noChanged();
        usleep(1000000);
    }
}

---------main.cpp----------------

#include <QQmlContext>
#include <QQuickView>
#include <QGuiApplication>
#include <QtQml>
#include "mytext.h"
int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    Thing myTh;
    QQuickView view;
    view.rootContext()->setContextProperty("qmyTh",&myTh);
    view.setSource(QUrl::fromLocalFile("main.qml"));
    view.show();
    return app.exec();
}

-------main.qml----------

import QtQuick 2.0;
Rectangle {
    id: root
    width: 200
    height: 200
    property var name: "test"
    Text {
        anchors.fill: parent
        text: name
    }
    MouseArea {
        anchors.fill: parent
        onClicked: {
            qmyTh.loop()
        }
    }
    Connections {
        target:qmyTh
        onQm_noChanged: {
            name = qmyTh.qm_no;
        } 
    }   
}

解释:

有一个类Thing,它的对象是myTh。类Thing的函数是提供一个可调用的函数,这里是loop。然后,此功能将持续更新m_no值并发出信号。现在的问题是,当无限循环不断更新要显示的值时,我如何更新Textname属性)?

代码对于QML部分(现在)来说是正确的,并且工作正常。不正确的是C++实现。如果删除while循环,保留其内容,并执行代码,您将看到文本已正确更新。

这种行为的原因应该在Qt quick render的实现中进行研究。在某些平台上,默认情况下渲染不带线程。我猜你正在使用Windows(请参阅此处的"Qt Quick")。因此,在非线程设置中,通过更新变量然后休眠,您将阻塞整个应用程序,从而阻止gui更新。

您可以使用QTimer每隔一段时间安排方法执行,也可以出于完全相同的目的设置QML Timer

此外,您不需要将新值保存在临时变量中(尤其是var,它在这种情况下添加了无用的检查)。通过在Text元素内设置id,可以直接设置文本属性。这里是重新访问的代码:

import QtQuick 2.0;
Rectangle {
    id: root
    width: 200
    height: 200
    Text {
        id: myText               // the id!
        anchors.fill: parent
        text: "dummy"            // dummy text || left empty || use "qmyTh.qm_no" (ensure a correct value is returned at creation time)
    }
    MouseArea {
        anchors.fill: parent
        onClicked: {
            qmyTh.loop()
        }
    }
    Connections {
        target:qmyTh
        onQm_noChanged: myText.text = qmyTh.qm_no    // text directly set!
    }
}

编辑

似乎使用的渲染是线程化的,因此我的推理不适用。应该还有其他问题。您可以尝试利用调试器并通过在JS处理程序中添加console.info(...)语句来跟踪问题。搜索问题可能有助于跟踪库中(可能的)错误。

根据你必须运行的后台处理,我仍然认为使用计时器不会那么糟糕。这真的,真的取决于你想要实现什么。然而,如果您想尝试线程,Qt文档中充满了解释(和往常一样)。看看这个,这个而且绝对如此。请注意,"移动"的对象(请参阅链接)不能注册为上下文属性,因此您必须使用其他方法之一来处理QML项目中的线程。