c++11iteratorstdmapstdarrayqquickitem

Adding QQuickItem pointers to an std::map makes them all "not accessible" pointers or items


This question involves Qt but could be pure C++ problem with my logic.

I am adding QQuickItems to an std::map store info about a list of QQuickItems & their respective parents.

The code:

std::array<std::string, 2> ObjectNamesArray = { "quickitemObj1", "quickitemObj2" };

std::map<QQuickItem*, QQuickItem*> items;

for(const auto& quickitem: ObjectNamesArray) {

    QQuickItem * item = Qmlengine->rootObjects()[0]->findChild<QQuickItem*>(quickitem.c_str());

    if (item != NULL)
       items.insert(std::make_pair(item, item->parent());

    // for a test, following works fine with the item pointer within this loop
    qreal width ? item->width();
}

Debugging through above loop, the items map shows zero items with the tag not accessible.

Iterating over the map again like this.

std::map<QQuickItem*, QQuickItem*>::iterator it = items.begin();
while (it != items.end()) {

    QQuickItem* item = it->first;
    QQuickItem * itemParent = it->second;  // crashes here as *item is null
    it++;
}

Problem:

But, when I try to iterate through the map, there are no valid pointers to my QQuickItems. In fact looks like there are not items added to the map.

Question:

What is wrong with my logic? How should I add QQuickItems to an std::map so that I can safely retrieve them back.


Solution

  • First you have const string inside this method istead of QQuickItem name

    findChild<QQuickItem*>("quickitem.c_str()");
    

    So it gives you 0
    You should add checking if item is NULL before adding to container.

    Second thing is that you talking about searching items map, but here, you are appending to parents

    parents.insert(std::make_pair(item, item->parent());
    

    BTW: When you use Qt, I recommend you using Qt containers

    EDIT:
    This works for me, after some improvements and if i have appropriate objects in QML


    CPP

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;
    
    std::array<std::string, 2> ObjectNamesArray = { "quickitemObj1", "quickitemObj2" };
    
    std::map<QQuickItem*, QQuickItem*> items;
    
    for(const auto& quickitem: ObjectNamesArray) {
    
        QQuickItem * item = engine.rootObjects()[0]->findChild<QQuickItem*>(quickitem.c_str());
    
        if (item != NULL)
           items.insert(std::make_pair(item, (QQuickItem*)item->parent()));
    }
    
    std::cout << "Map: " << items.size() << std::endl; //it gives 2
    
    std::map<QQuickItem*, QQuickItem*>::iterator it = items.begin();
    while (it != items.end()) {
    
        QQuickItem* item = it->first;
        QQuickItem * itemParent = it->second;  // no crash
        it++;
    }
    

    QML

    import QtQuick 2.6
    import QtQuick.Window 2.2
    
    Window {
        visible: true
        width: 640
        height: 480
        title: qsTr("Hello World")
    
        Item
        {
            objectName: "quickitemObj1"
        }
        Item
        {
            objectName: "quickitemObj2"
        }
    }