如何从C++中设置QML属性

7

我想要做的事情很简单,就是从C++更改一些QML对象的属性(文本:) ,但是我失败了。任何帮助都将不胜感激。

我没有收到任何错误消息,窗口显示出来了,只是文本属性没有像应该一样改变。 我甚至有没有错过什么?!

我尝试的是这个:

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickView>
#include <QQuickItem>
#include <QQmlEngine>
#include <QQmlComponent>
#include <QString>

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;


    QQmlComponent component(&engine, QUrl::fromLocalFile("main.qml"));
    QObject *object = component.create();

     engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    QString thisString = "Dr. Perry Cox";

    object->setProperty("text", thisString);  //<--- tried  instead of thisString putting "Dr. ..." but nope.
    delete object;



    return app.exec();
}

main.qml

import QtQuick 2.2
import QtQuick.Window 2.1

Window {
    visible: true
    width: 360
    height: 360

    MouseArea {
        anchors.fill: parent
        onClicked: {
            Qt.quit();
        }
    }

    Text {
        id: whot
        text: ""
        anchors.centerIn: parent
        font.pixelSize: 20
        color: "green"
    }
}

1
https://qt-project.org/doc/qt-5-snapshot/qtqml-cppintegration-interactqmlfromcpp.html - Retired Ninja
谢谢您提供的链接,退役忍者(顺便说一下,我喜欢您的名字)。但那正是我开始的地方,我做了那里的示例,想尝试更改一些其他属性,比如文本(不仅仅是宽度和高度)。也许我有点弱智,但我从文档中学不到任何东西。 - hekri
2
我想如果你还没看到,这可能会有所帮助。从那个链接中关于深入树形结构操作对象的警告可能是最有用的部分。你尝试做的事情可能不是最好的方式。我们曾经像文档中描述的那样为子项分配唯一名称以访问它们,但是给很多东西分配唯一名称是很麻烦的。现在通常我们只使用绑定到C++提供的属性或信号来使QML保持同步,我们更加满意。 - Retired Ninja
那么您的意思是我应该深入研究文档,还是有其他信息来源可以让我学到一些东西? - hekri
3个回答

6
当您调用QObject *object = component.create();时,您可以访问根上下文,即Window组件及其属性。
要访问Text属性,您可以创建属性别名,如下所示:
Window {
    property alias text: whot.text
    ...
    Text {
        id: whot
        text: ""
        ...
    }
}

这将允许您从Window上下文中访问whottext属性。

还有一种稍微绕一些的方法。将whotobjectName属性分配给id(如果您仍然需要id,则同时分配两者):

Text {
    id: whot // <--- optional
    objectName: "whot" // <--- required
    text: ""
    ...
 }

现在你可以通过代码来实现这个功能:
QObject *whot = object->findChild<QObject*>("whot");
if (whot)
    whot->setProperty("text", thisString);

顺便提一下:我认为在调用app.exec()之后再删除object,否则会被删除。


谢谢你的回答。是的,这就是为什么一开始设置了一个id(id:whot),但是id仍然没有起作用。在你的回答之后再次进行了双重检查,但是还是不行。 - hekri
1
@herki,我更新了答案。我仍然在使用Qt 4.8,所以需要一些时间来适应你的示例。请检查delete object;语句。我认为它应该在调用app.exec()之后。 - Super-intelligent Shade
谢谢你的努力,我非常感激,但它仍然无法工作。奇怪的是,在删除对象之前放置app.exec()后,另一个窗口会显示出一个“Hello World”?!我甚至不知道那是从哪里来的。 - hekri
@hekri,哦,是的,我差点忘了——你需要删除engine.load(...)这一行。它正在从你的资源文件中加载东西。 - Super-intelligent Shade
1
@hekri,似乎还有其他问题。你的项目中是否有一个资源(.qrc)文件?我做出了以下几个假设:(a)你已经将“delete object”行移动到了“app.exec()”之后;(b)你已经删除了“engine.load()”行和(c)你已经尝试了我上面列出的两个版本。如果没有,请执行这些操作。否则,可以尝试一些方法:(1)在qml文件中用类似“text: 'foobar'”这样的语句替换“text: ''”,看看它是否会显示在窗口中。(2)从头开始创建一个新项目,只添加以上两个文件,并查看是否正常工作。对我来说是有效的(尽管在Qt 4.8上)。 - Super-intelligent Shade
显示剩余3条评论

0
#include <QQmlContext>
#include <qquickview.h>
#include <qdir.h>

QQmlApplicationEngine engine;
QString root = QCoreApplication::applicationDirPath();
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
        return -1;
QObject *topLevel = engine.rootObjects().value(0);
QQuickWindow *window = qobject_cast<QQuickWindow*>(topLevel);
window->setProperty("root", root);

用于 QML

ApplicationWindow  {
    property string root
    onRootChanged: {
        console.log("root : "+ root);
    }
}

0

对于 QML 属性,您应该使用 QQmlProperty

QQmlProperty::write(whot, "text", thisString);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接