[Qt-qml] Problem with finding qml elements placed within ListView delegate from C++ code

mathias.malmqvist at nokia.com mathias.malmqvist at nokia.com
Mon Jul 11 15:05:32 CEST 2011


Although Bea is correct, this is a really bad practice. The internal 
implementation of the ListView is not part of the public API and 
can change at any time (e.g. when switching to scene graph 
drawing), and the ListView also manage the lifetime of the list 
items so there's no grantee that the objects you're accessing 
won't just be deleted by the ListView.

Much better to make your list items access your c++ code than 
the other way around.


Cheers
Mathias

________________________________________
From: qt-qml-bounces+mathias.malmqvist=nokia.com at qt.nokia.com [qt-qml-bounces+mathias.malmqvist=nokia.com at qt.nokia.com] on behalf of ext bea.lam at nokia.com [bea.lam at nokia.com]
Sent: Monday, July 11, 2011 4:06 AM
To: dshakhovski at gmail.com
Cc: qt-interest at qt.nokia.com; qt-qml at qt.nokia.com
Subject: Re: [Qt-qml] Problem with finding qml elements placed within ListView delegate from C++ code

On 08/07/2011, at 4:19 AM, ext Дмитрий Шаховский wrote:

> Hi,
> I have a problem when I tried to find a qml element placed within ListView delegate from C++ code.
>
> E.g.
>
> Rectangle {
>    ...
>    ListView{
>        ...
>        delegate: Rectangle{
>                      objectName: "rect"
>                  }
>
>        model: ListModel{
>                   ListElement{}
>                   ListElement{}
>                   ListElement{}
>               }
>    }
> }
>
> And somewhere in C++ code
>
> QDeclarativeView *view = new QDeclarativeView;
> view->setSource(QUrl::fromLocalFile("myqmlfile.qml"));
> QObject* rootObject = view->rootObject();
> QObject* obj = rootObject->findChild<QObject*>("rect");
>
> obj will be null.


QObject::findChild() won't find the delegate objects because they are added as "child items" in the graphics scene, rather than child objects in the QObject* hierarchy. Child items in a graphics scene are accessible through QGraphicsItem::childItems().

Also, ListView inherits from Flickable, and delegate items within a Flickable are parented to a separate item that holds the contents of the Flickable, rather than the Flickable itself. This separate item is accessible through the 'contentItem' property:  http://doc.qt.nokia.com/4.7/qml-flickable.html#contentItem-prop

So to find a delegate instance within the view, add an objectName to the view:


ListView {
        objectName: "view"


and in main.cpp:

    QObject *listView = rootObject->findChild<QObject*>("view");
    QDeclarativeItem *contentItem = qvariant_cast<QDeclarativeItem*>(listView->property("contentItem"));

    foreach (QGraphicsItem *item, contentItem->childItems()) {
        if (qobject_cast<QDeclarativeItem*>(item)->objectName() == "rect") {
            qDebug() << "Found:" << item;
        }
    }

>
> in C++ slot connected to rectClicked signal
>
> void SomeObject::onRectClicked(QVariant element)
> {
>    QObject* rootObject = declarativeView->rootObject();
>    QObject* listView = rootObject->findChild<QObject*>("listView");
>
>    QObject* obj = element.value<QObject*>()->parent()->parent();
>    //obj will be null instead of the equality of listView
>    //(element.value<QObject*>() is QDeclarativeRectangle)
> }
>
> So delegate component children are not in root object's tree.

Yes, calling QObject::parent() here is referring to the QObject* parent, rather than the parent item in the graphics scene. In QML, referring to item.parent actually refers to the QDeclarativeItem* parent item, not the QObject* parent (as you can see by the QDeclarativeItem::parent docs).


regards,

Bea

_______________________________________________
Qt-qml mailing list
Qt-qml at qt.nokia.com
http://lists.qt.nokia.com/mailman/listinfo/qt-qml


More information about the Qt-qml mailing list