7

I'm trying to do a simple task as changing a property (text: ) of some QML object from C++ yet I'm failing miserably. Any help appreciated.

I'm not getting any errors, the window shows up, just the text property doesn't change as (at least I think) it should. Is even anything I'm NOT doing wrong here?!!

What I was trying is this:

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"
    }
}
Ankit
  • 1,330
  • 2
  • 11
  • 16
hekri
  • 307
  • 3
  • 11
  • 1
    https://qt-project.org/doc/qt-5-snapshot/qtqml-cppintegration-interactqmlfromcpp.html – Retired Ninja Dec 20 '14 at 22:38
  • Thank you for the link Retired Ninja (like your name btw) but that's exactly where I started from, I did the example there and thought I'd try and change some other property like text (not just width and height). Maybe I'm a little bit retarded but I can't learn a (insert bad word here) from the documentation. – hekri Dec 20 '14 at 22:42
  • 2
    I figured in case you hadn't seen that it might help. The warning about manipulating objects deep in the tree from that link is probably the best part. What you're attempting to do probably isn't the best way to go about it. We used to do something like what was described in the docs and access child items by name, but assigning a unique name to a bunch of things is a pain. Generally now we just use bindings to properties provided by c++ or signals to keep the qml in sync and we're much happier. – Retired Ninja Dec 20 '14 at 23:03
  • So you mean I shall dig deeper in the documentation or is there any other source of information from where I could possible learn something? – hekri Dec 20 '14 at 23:25

3 Answers3

6

When you call QObject *object = component.create(); you get access to the root context, which is the Window component and its properties.

To get access to Text properties, you can create property alias like this:

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

That will give you access to whot's text property from within the Window's context.

There is another slightly more round-about way. Assign objectName property instead of id (or both if you still need id) to whot:

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

Now you can do this in code:

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

On a side note: I don't think you are supposed to delete the object until after calling app.exec(). Otherwise, it will ... well, be deleted. :)

  • Thank you for the answer. Yes, that's why set an id (id:whot) in the first place, but still id didn't work. Double checked it after your anser but no, not working. – hekri Dec 20 '14 at 22:39
  • 1
    @herki, I updated the answer. I am still on Qt 4.8, so it took some time to adapt your example. Check that `delete object;` statement. I think it should be after you call `app.exec()`. – Super-intelligent Shade Dec 20 '14 at 22:54
  • Thnx for the effort, I appreciate it a lot but it still doesn't work. Strangely after putting app.exec() before the delete object another window shows up with a "Hello World" on it?!! I don't even know where that comes from. – hekri Dec 20 '14 at 23:04
  • @hekri, oh yeah, almost forgot -- you need to remove the `engine.load(...)` line. It's loading stuff from your resource file – Super-intelligent Shade Dec 20 '14 at 23:08
  • Still not working. A window shows up but says "Hello World" instead of "thisString". The strange thing is I don't know where that "hello World" comes from. Font size and color are like those of the text i'm trying to "print out". – hekri Dec 20 '14 at 23:24
  • 1
    @hekri, something else seems to be wrong. Do you have a resource (.qrc) file in your project? I am making following assumptions: (a) you have moved the `delete object` line below `app.exec()`; (b) you have removed the `engine.load()` line and (c) you have tried both versions I list above. If not, please do these. Otherwise, a few things to try: (1) in the qml file replace `text: ""` with something like `text: "foobar"` and see if it shows up in the window. (2) Create a new project from scratch and add just the 2 above files to it and see if it works. It works for me (albeit on Qt 4.8). – Super-intelligent Shade Dec 20 '14 at 23:35
  • It worked the first method after I created a new project. Thank you. – hekri Dec 20 '14 at 23:50
  • @hekri, You got it, big guy. – Super-intelligent Shade Dec 21 '14 at 01:01
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);

for qml

ApplicationWindow  {
    property string root
    onRootChanged: {
        console.log("root : "+ root);
    }
}
Mahdi Khalili
  • 1,025
  • 15
  • 32
0

For QML properties you should use QQmlProperty instead:

QQmlProperty::write(whot, "text", thisString);
jhasse
  • 2,379
  • 1
  • 30
  • 40