Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QGraphicsScene returns items() in wrong order when using QGraphicsScene::NoIndex



  • Hi,

    The documentation of QGraphicsScene::items says that items(Qt::DescendingOrder) will return an ordered list of all items in descending order. However I get an unordered list after removing an item from the scene when the index method is set to QGraphicsScene::NoIndex. For example, the scene before deletion contains three items:

    items[0]: QGraphicsItem(0x15aba90, pos=0,0)
    items[1]: QGraphicsItem(0x15aa310, pos=0,0)
    items[2]: QGraphicsItem(0x15aa2f0, pos=0,0)

    I use QGraphicsScene::removeItem to remove the last item from the scene, and QGraphicsScene::items returns

    items[0]: QGraphicsItem(0x15aa310, pos=0,0)
    items[1]: QGraphicsItem(0x15aba90, pos=0,0)

    Why the first item in the list is not QGraphicsItem(0x15aba90)?
    When I ran the program several times, I got different results - the order wasn't always changed.

    Full code (Qt5.5, Ubuntu 14.04):

    #include <QApplication>
    
    #include <QGraphicsRectItem>
    #include <QGraphicsPixmapItem>
    #include <QGraphicsScene>
    #include <QDebug>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
    
        auto scene = new QGraphicsScene;
        scene->setItemIndexMethod(QGraphicsScene::NoIndex);
    
        scene->addItem(new QGraphicsRectItem(QRect()));
        scene->addItem(new QGraphicsRectItem(QRect()));
        auto last_item = new QGraphicsRectItem(QRect());
        scene->addItem(last_item);
    
        qDebug() << "before deletion:";
        auto items = scene->items();
        qDebug() << "\titems[0]: " << items[0];
        qDebug() << "\titems[1]: " << items[1];
        qDebug() << "\titems[2]: " << items[2];
    
        scene->removeItem(last_item);
    
        qDebug() << "after deletion:";
        items = scene->items();
        qDebug() << "\titems[0]: " << items[0];
        qDebug() << "\titems[1]: " << items[1];
        return a.exec();
    }
    


  • @flora_teeemoooooo
    "Descending order" refers to the Z-Order of items, not pointers or anything else. Unless you specified a Z-Value (which you didn't) the z-order depends on the order in which you inserted items - last item is on top.

    Now it's hard to say anything more, because the pointer values you post on top do not relate to the source code in any manner. You can improve the test by giving each item a distinct position (e.g. 1/1, 2/2, 3/3 in order of insertion), then you should see that the last item inserted comes first in the items list.



  • Hi,

    Thank you for your advice.
    I set the z-values manually and got the similar result. Does QGraphicsScene::NoIndex imply there is no guarantee that items() will return an ordered list?

    before deletion:
    items[0] z-value: 2
    items[1] z-value: 1
    items[2] z-value: 3
    after deletion:
    items[0] z-value: 2
    items[1] z-value: 1
    Is there any errors in the test code?

    Full code:

    #include <QApplication>
    
    #include <QGraphicsRectItem>
    #include <QGraphicsPixmapItem>
    #include <QGraphicsScene>
    #include <QDebug>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
    
        auto scene = new QGraphicsScene;
        scene->setItemIndexMethod(QGraphicsScene::NoIndex);
    
        auto item0 = new QGraphicsRectItem(QRect());
        item0->setZValue(2);
        scene->addItem(item0);
        auto item1 = new QGraphicsRectItem(QRect());
        item1->setZValue(1);
        scene->addItem(item1);
        auto item2 = new QGraphicsRectItem(QRect());
        item2->setZValue(3);
        scene->addItem(item2);
    
        qDebug() << "before deletion:";
        auto items = scene->items();
        qDebug() << "\titems[0] z-value: " << items[0]->zValue();
        qDebug() << "\titems[1] z-value: " << items[1]->zValue();
        qDebug() << "\titems[2] z-value: " << items[2]->zValue();
    
        scene->removeItem(item2);
    
        qDebug() << "after deletion:";
        items = scene->items();
        qDebug() << "\titems[0] z-value: " << items[0]->zValue();
        qDebug() << "\titems[1] z-value: " << items[1]->zValue();
        return a.exec();
    }
    


  • It could indeed be a bug. I haven't found one that describes what you write, but it might be the cause for this one:
    https://bugreports.qt.io/browse/QTBUG-13708

    I suggest that you submit a bug report for this. But don't get your hopes too high for a quick fix - GraphicsView is not a first class citizen in Qt anymore.



  • Thank you very much. I'll check the link and submit a bug.


Log in to reply