Techdojo
Techdojo

Reputation: 123

QML newbie needing help accessing Item properties from within C++

I am developing an application in QT and QML to access some XML data and display the results.

The XML is downloaded / parsed from C++ and this works fine. I have a QML application designed to display the custom layout and that also works fine.

To make the app look more polished I have an initial "splash screen" that's displayed whilst the C++ side completes the initial download / parse, I have created a property inside the main QML view to represent the current application "state" so I can swap to the correct screen when the data is ready.

Main.qml

Item
{
   id: mainScreen
   width: 800; height: 600;   
   property int activeState: 0       // This controls what screen is displayed

   Item 
   {
       // screen layout .. removed .. 
   }
}

The C++ code is generated by the QT creator app wizard and is based around the basic QmlApplicationViewer class.

I've read (and re-read) the online QT docs and supposedly all I have to do to access the individual properties of mainScreen is to call the findChild<QObject *> method of the application viewers rootContext() to return a QObject pointer to the mainScreen instance and then call the setProperty method like so.

QObject *mainView = ROOT_CONTEXT->findChild<QObject *>("mainScreen");

qDebug("mainView = %08X",(uint)mainView);

if(mainView)
{
    mainView->setProperty("activeState",1);
}
else
    qDebug("Unable to find the mainScreen QML object");

Where ROOT_CONTEXT is defined elsewhere as

QDeclarativeContext *ROOT_CONTEXT;
QDeclarativeEngine  *ROOT_ENGINE;
QGraphicsObject     *ROOT_OBJECT;

void QmlApplicationViewer::createMyApplication(void)
{
    ROOT_CONTEXT = this->rootContext();
    ROOT_OBJECT  = this->rootObject();
    ROOT_ENGINE  = this->engine();

    pMyApplication = new MyApplication(this);
}

and void QmlApplicationViewer::createMyApplication(void) is called after the main QML file has been setup ie

QmlApplicationViewer viewer;

viewer.setMainQmlFile(QLatin1String("main.qml"));
viewer.showExpanded();
viewer.createMyApplication();

BUT...

The problem I'm running into is that that the value returned from findChild<QObject *>("mainScreen"); is always NULL. I've tried enumerating through the hierarchy of objects in my QML file using the following code

QList<QObject*> list = ROOT_OBJECT->findChildren<QObject*>();

qDebug("list = %d",list.count());
int i;

for(i=0;i<list.count();i++)
{
    QObject *obj = list[i];

    qDebug() << "Object" << i << obj->objectName();
}

and I get a list of ~120 items but they all have a blank string ("") for their name.

Looking back at the QT docs all the examples seem to suggest creating the individual parts by hand (ie creating an instance of QDeclarativeEngine, QDeclarativeComponent and QDeclarativeItem) and linking them together instead of using the QApplicationViewer class as shown on this blog entry http://xizhizhu.blogspot.co.uk/2010/10/hybrid-application-using-qml-and-qt-c.html, but I'd much rather stick with the code I've already written.

Can anyone please help and suggest where I'm going wrong or point me in the direction where I can find a "simple" example of being able to change a property of an Item in a QML file from C++.

Many (many) thanks in advance.

Jon...

Upvotes: 2

Views: 2094

Answers (2)

Techdojo
Techdojo

Reputation: 123

UPDATE

The following code

QList<QObject*> list = ROOT_OBJECT->findChildren<QObject*>();

qDebug("list = %d",list.count());
int i;

for(i=0;i<list.count();i++)
{
    QObject *obj = list[i];
    qDebug() << "Object" << i << obj->objectName();
}

Works and dumps out the list of objects and when I use the objectName: property in my QML files as mentioned above I can see (and access) the children of the ROOT Item in my application.

What I can't seem to do however is actually access the ACTUAL ROOT item and set it's properties - it them dawned on me in a typical face palm moment that I ALREADY HAD A REFERENCE TO THE ROOT OBJECT! It's was the value already stored in the ROOT_OBJECT variable * sheesh *

So in summary...

All of the above code works - to actually find and adjust the properties of a CHILD off the main view, remember to set the objectName:, if you want to actually change a property IN the root item - just use the value returned by the QDeclaritiveView::rootObject() function.

Thanks again to IvanFel for pointing me in the right direction, Hopefully this will show up in a search sometime and help someone else in the same way that a lot of stackOverflow entries have helped me in the past.

8-)

Upvotes: 3

ivanfeli
ivanfeli

Reputation: 230

Main.qml should be

Item
{
   id: mainScreen
   objectName: "mainScreen"
   width: 800; height: 600;   
   property int activeState: 0       // This controls what screen is displayed

   Item 
   {
       // screen layout .. removed .. 
   }
}

You were missing the objectName: "mainScreen", that's how findChild<>() finds it's children.

Upvotes: 2

Related Questions