Search code examples
qtqt4qmlqt-quick

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...


Solution

  • 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.