Как установить свойства QML из C++

Я пытаюсь выполнить простую задачу по изменению свойства (text:) некоторого объекта QML из C++, но я терплю неудачу. Любая помощь приветствуется.

Я не получаю никаких ошибок, появляется окно, просто свойство text не изменяется так, как (по крайней мере, я думаю), должно. Есть ли хоть что-то, что я НЕ делаю неправильно здесь?!!

Я пытался это:

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"
    }
}

person hekri    schedule 20.12.2014    source источник
comment
qt-project.org/doc/qt-5- снимок/   -  person Retired Ninja    schedule 21.12.2014
comment
Спасибо за ссылку Отставной ниндзя (кстати, ваше имя), но именно с этого я и начал, я сделал пример и подумал, что попробую изменить какое-то другое свойство, например текст (не только ширину и высоту). Может быть, я немного отсталый, но я не могу узнать (вставьте здесь плохое слово) из документации.   -  person hekri    schedule 21.12.2014
comment
Я подумал, если ты не видел, что это может помочь. Предупреждение о манипулировании объектами глубоко в дереве из этой ссылки, вероятно, лучшая часть. То, что вы пытаетесь сделать, вероятно, не лучший способ сделать это. Раньше мы делали что-то вроде того, что описано в документации, и обращались к дочерним элементам по имени, но присваивать уникальное имя множеству вещей — это боль. Как правило, теперь мы просто используем привязки к свойствам, предоставляемым C++, или сигналы, чтобы синхронизировать qml, и мы намного счастливее.   -  person Retired Ninja    schedule 21.12.2014
comment
Итак, вы имеете в виду, что я должен копаться в документации или есть какой-либо другой источник информации, из которого я мог бы что-то узнать?   -  person hekri    schedule 21.12.2014


Ответы (3)


Когда вы вызываете QObject *object = component.create();, вы получаете доступ к корневому контексту, который является компонентом Window и его свойствами.

Чтобы получить доступ к свойствам Text, вы можете создать псевдоним свойства следующим образом:

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

Это даст вам доступ к свойству text whot из контекста Window.

Есть еще один, чуть более окольный путь. Назначьте свойство objectName вместо id (или обоих, если вам все еще нужно id) для whot:

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

Теперь вы можете сделать это в коде:

QObject *whot = object->findChild<QObject*>("whot");
if (whot)
    whot->setProperty("text", thisString);

На заметку: я не думаю, что вы должны удалять object до тех пор, пока не вызовете app.exec(). В противном случае он будет... ну, удален. :)

person Innocent Bystander    schedule 20.12.2014
comment
Спасибо за ответ. Да, именно поэтому сначала установили идентификатор (id:whot), но все равно идентификатор не работал. Дважды проверил это после вашего ответа, но нет, не работает. - person hekri; 21.12.2014
comment
@herki, я обновил ответ. Я все еще на Qt 4.8, поэтому потребовалось некоторое время, чтобы адаптировать ваш пример. Проверьте это утверждение delete object;. Я думаю, что это должно быть после того, как вы позвоните app.exec(). - person Innocent Bystander; 21.12.2014
comment
Спасибо за усилия, я очень ценю это, но это все еще не работает. Как ни странно, после помещения app.exec() перед объектом удаления появляется другое окно с надписью Hello World?!! Я даже не знаю, откуда это. - person hekri; 21.12.2014
comment
@hekri, ах да, чуть не забыл - тебе нужно удалить строку engine.load(...). Он загружает материал из вашего файла ресурсов - person Innocent Bystander; 21.12.2014
comment
До сих пор не работает. Появится окно, но вместо thisString будет написано Hello World. Странно то, что я не знаю, откуда взялся этот привет, мир. Размер и цвет шрифта такие же, как у текста, который я пытаюсь распечатать. - person hekri; 21.12.2014
comment
@hekri, кажется, что-то еще не так. У вас есть файл ресурсов (.qrc) в вашем проекте? Я делаю следующие предположения: (а) вы переместили строку delete object ниже app.exec(); (б) вы удалили строку engine.load() и (в) вы попробовали обе версии, которые я перечислил выше. Если нет, пожалуйста, сделайте это. В противном случае попробуйте несколько вещей: (1) в файле qml замените text: "" чем-то вроде text: "foobar" и посмотрите, появится ли он в окне. (2) Создайте новый проект с нуля и добавьте в него только 2 вышеуказанных файла и посмотрите, работает ли он. У меня работает (хотя и на Qt 4.8). - person Innocent Bystander; 21.12.2014
comment
Первый метод сработал после того, как я создал новый проект. Спасибо. - person hekri; 21.12.2014
comment
@hekri, ты понял, большой парень. - person Innocent Bystander; 21.12.2014

#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);
    }
}
person Mahdi Khalili    schedule 25.09.2018

Для свойств QML вместо этого следует использовать QQmlProperty:

QQmlProperty::write(whot, "text", thisString);
person jhasse    schedule 31.03.2021