【问题标题】:How to set QML properties from C++如何从 C++ 设置 QML 属性
【发布时间】:2021-03-31 22:48:25
【问题描述】:

我正在尝试做一个简单的任务,例如从 C++ 更改某些 QML 对象的属性(文本:),但我失败了。任何帮助表示赞赏。

我没有收到任何错误,窗口出现了,只是 text 属性没有改变(至少我认为)它应该改变。 有什么我没有做错的吗?!!

我正在尝试的是:

ma​​in.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();
}

ma​​in.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"
    }
}

【问题讨论】:

  • 感谢 Retired Ninja 的链接(就像你的名字顺便说一句),但这正是我开始的地方,我在那里做了示例,并认为我会尝试更改一些其他属性,例如 text(不仅仅是宽度和高度)。也许我有点迟钝,但我无法从文档中学习(在此处插入坏词)。
  • 我想如果你没有看到它可能会有所帮助。关于从该链接操纵树深处的对象的警告可能是最好的部分。您尝试做的事情可能不是最好的方法。我们曾经做类似文档中描述的事情并通过名称访问子项,但是为一堆东西分配一个唯一的名称是一件痛苦的事情。一般来说,现在我们只需使用 c++ 提供的属性或信号的绑定来保持 qml 同步,我们会更开心。
  • 所以你的意思是我应该深入研究文档,或者是否有任何其他信息来源可以从中学到一些东西?

标签: c++ qml qt5.4


【解决方案1】:

当您调用QObject *object = component.create(); 时,您可以访问根上下文,即Window 组件及其属性。

要访问Text 属性,您可以像这样创建属性别名:

Window {
    property alias text: whot.text
    ...
    Text {
        id: whot
        text: ""
        ...
    }
}

这将使您能够从Window 的上下文中访问whottext 属性。

还有另一种稍微迂回的方式。将objectName 属性而不是id(或者如果您仍然需要id)分配给whot

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 仍然不起作用。在你的分析器之后仔细检查了它,但没有,没有工作。
  • @herki,我更新了答案。我仍在使用 Qt 4.8,因此需要一些时间来调整您的示例。检查delete object; 语句。我想应该是在你打电话给app.exec()之后。
  • 感谢您的努力,我非常感谢它,但它仍然不起作用。奇怪的是,将 app.exec() 放在删除对象之前,另一个窗口出现了一个“Hello World”?!我什至不知道这是从哪里来的。
  • @hekri,哦,是的,差点忘了——您需要删除 engine.load(...) 行。它正在从您的资源文件中加载内容
  • @hekri,似乎还有其他问题。您的项目中有资源 (.qrc) 文件吗?我做出以下假设:(a)您已将delete object 行移至app.exec() 下方; (b) 你已经删除了engine.load() 行并且(c) 你已经尝试了我上面列出的两个版本。如果没有,请做这些。否则,可以尝试一些事情: (1) 在 qml 文件中将 text: "" 替换为 text: "foobar" 之类的内容,然后查看它是否显示在窗口中。 (2) 从头开始​​创建一个新项目,将上面的 2 个文件添加到其中,看看它是否有效。它对我有用(尽管在 Qt 4.8 上)。
【解决方案2】:
#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);
    }
}

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-02-27
      • 2014-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-26
      • 1970-01-01
      相关资源
      最近更新 更多