QML 中的线程渲染器
Threaded renderer in QML
线程渲染器在以下代码中不工作。我在带有专有驱动器的 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;
}
}
}
解释::
有一个 classes Thing
,其对象 myTh
。 classThing
的作用是提供一个可调用的函数,这里是loop
。然后,此函数将不断更新 m_no
值并发出信号。现在的问题是我如何更新 Text
(name
属性) 而无限循环是 运行 不断更新要显示的值?
代码对于 QML 部分(现在)是正确的,并且可以正常工作。不正确的是 C++ 实现。如果您删除 while
循环,保留其内容并执行您的代码,您将看到文本已正确更新。
应在 Qt quick render
实施中研究此类行为的原因。在某些平台上,默认情况下渲染不是线程化的。我猜你正在研究 Windows(参见 "Qt Quick" here)。因此,在非线程设置中,通过更新变量然后休眠,您将阻塞 whole 应用程序,从而阻止 gui 更新。
您可以使用 QTimer
to schedule the method execution at intervals, or set up a 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 文档中有很多解释(和往常一样)。
看看 this, this
而且绝对 this。请注意,"moved" 对象(请参阅链接)不能注册为上下文 属性,因此您必须使用其他方法之一来处理 QML 项目中的线程。
线程渲染器在以下代码中不工作。我在带有专有驱动器的 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;
}
}
}
解释::
有一个 classes Thing
,其对象 myTh
。 classThing
的作用是提供一个可调用的函数,这里是loop
。然后,此函数将不断更新 m_no
值并发出信号。现在的问题是我如何更新 Text
(name
属性) 而无限循环是 运行 不断更新要显示的值?
代码对于 QML 部分(现在)是正确的,并且可以正常工作。不正确的是 C++ 实现。如果您删除 while
循环,保留其内容并执行您的代码,您将看到文本已正确更新。
应在 Qt quick render
实施中研究此类行为的原因。在某些平台上,默认情况下渲染不是线程化的。我猜你正在研究 Windows(参见 "Qt Quick" here)。因此,在非线程设置中,通过更新变量然后休眠,您将阻塞 whole 应用程序,从而阻止 gui 更新。
您可以使用 QTimer
to schedule the method execution at intervals, or set up a 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 文档中有很多解释(和往常一样)。 看看 this, this 而且绝对 this。请注意,"moved" 对象(请参阅链接)不能注册为上下文 属性,因此您必须使用其他方法之一来处理 QML 项目中的线程。