Issue with QGraphicsItemGroup subclass



  • Hi,
    I created a very basic subclass of QGrahpicsItemGroup to handle some special requirements with groups. This is my code:

    MyItemGroup::MyItemGroup(QGraphicsItem *parent) : QGraphicsItemGroup(parent)
    {
    }
    
    MyItemGroup::~MyItemGroup()
    {
    }
    
    QVariant MyItemGroup::itemChange(GraphicsItemChange change, const QVariant &value)
    {
        if (change == QGraphicsItem::ItemChildAddedChange) {
            QGraphicsItem *item = qvariant_cast<QGraphicsItem *>(value);
            if (!children.contains(item))
                children << item;
        }
    
        return QGraphicsItemGroup::itemChange(change, value);
    }
    
    void MyItemGroup::recoverChildren()
    {
        int total = children.count();
        for(int i=0; i<total; i++) {
            QGraphicsItem *item = children.at(i);
    
            if (MyItemGroup *child = qgraphicsitem_cast<MyItemGroup *>(item))
                child->recoverChildren();
    
            if (item->parentItem() != this)
                item->setParentItem(this);
        }
    }
    
    QList<QGraphicsItem *> MyItemGroup::groupChildren()
    {
        return children;
    }
    

    This is the way I create an object of this subclass:

    MyItemGroup *itemGroup = new MyItemGroup;
    foreach (QGraphicsItem *item, selectionList)
             itemGroup->addToGroup(item);
    itemGroup->recoverChildren();
    

    This is the way I add the MyItemGroup objects into my QGraphicsScene:

    group->recoverChildren(); // If I remove this line, group objects get invisible :(
    addItem(group);
    

    Now, this is the issue I want to discuss with you: As far as I am adding new group objects into my scene and I start to update my view, then some of the group objects start to change the order of its inner items (the Z value specifically) in a random way. So, the item in the back appears in the front of the group and things like that, deforming the original shape.

    Questions: What I am doing wrong to lose the original z-order of the items within my groups? Is there a way to keep it every time I paint the scene?

    Thanks!


  • Qt Champions 2016

    Hello,
    If I were to hazard a guess I'd say your reparenting of items is wrecking havoc on their positions. I can't seem to understand what exactly you're trying to achieve with this code. MyItemGroup::recoverChildren looks like recursively reparents all the items it holds reference to and MyItemGroup::itemChange updates the children list ... what is the purpose of that? Why do you want to subclass the group in the first place, as it is in your sample it doesn't really suggest necessity?

    Kind regards.



  • Hi,
    In fact, at the beginning I started using the QGraphicsItemGroup class to handle groups of shapes in a very basic way:

    QGraphicsItemGroup *group = new QGraphicsItemGroup;
    foreach (QGraphicsItem *item, graphicsList)
             group->addToGroup(item);
    addItem(group);
    

    But, as soon as I added new groups into the scene and the view was refreshed, some items of the groups became invisible for no reason. It's a random behaviour but when any item of a group disappears, I can't make it visible any more.

    So, I decided to try a subclass. Some of the weird tricks you see in there have helped me to avoid the problem I had described above but now I have the problem of the z-value mess.

    I would like to see a basic but clean implementation of a scene working with groups without any strange behaviour. I understand I am missing something, using a subclass or not.

    I have been working with simple QGraphicsItem objects and the same code without any issue. But now that I am playing with the QGraphicsItemGroup class it seems a different game.

    Any suggestion?


  • Qt Champions 2016

    @xtingray
    Hello,
    As far as I can tell when you add items to a group an automatic remapping of coordinates occurs as well as reparenting of the objects, so creating it like you do might jumble that up (I'm speculating here). Have you tried creating your groups directly from the scene with the QGraphicsScene::createItemGroup method?
    Take a look at the note about groups in the graphics view framework overview.

    Kind regards.



  • After trying many approaches using QGraphicsItemGroup objects, finally I could write a subclass that fixes all the issues I found out while I was using the native class for item groups (while I was refreshing the view, either some of the group items disappeared in a random way or the zvalue of the items got messy).
    This is my final code in case some else is interested:

    MyItemGroup::MyItemGroup(QGraphicsItem *parent) : QGraphicsItemGroup(parent)
    {
    }
    
    MyItemGroup::~MyItemGroup()
    {
    }
    
    void MyItemGroup::addToGroup(QGraphicsItem *item)
    {
        children << item;
        QGraphicsItemGroup::addToGroup(item);
    }
    
    void MyItemGroup::recoverChilds()
    {
        int total = children.count();
        for(int i=0; i<total; i++) {
            QGraphicsItem *item = children.at(i);
            item->setZValue(i);
    
            if (MyItemGroup *child = qgraphicsitem_cast<MyItemGroup *>(item))
                child->recoverChilds();
            
            if (item->parentItem() != this)
                item->setParentItem(this);
        }
    }
    
    QList<QGraphicsItem *> MyItemGroup::childItems()
    {
        return children;
    }
    

    In my scene view I had to do this to avoid any issue:

    void MyScene::includeObject(QGraphicsItem *item)
    {
        if (MyItemGroup *group = qgraphicsitem_cast<MyItemGroup *>(item))
            group->recoverChilds();
        addItem(item);
    }
    

    @kshegunov Thank you for your comments! They led me to the solution in some way :)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.