Problem with delete QGraphicsSvgItem.



  • I have bad feeling, that this is maybe stupid question, but I don´t know what is wrong.
    This code doesn´t work. I cannot delete the items. Items which I want to delete are from my class:

    @class graphicsSvgItem : public QGraphicsSvgItem@

    code:

    @void MainWindow::deleteFigure()
    {
    QList<QGraphicsItem *> list = scene->items();
    for (int i=0;i<list.count();i++) //list of graphics object
    {
    if (list[i]->flags() & list[i]->ItemIsMovable)
    {
    scene->removeItem(list[i]);
    //delete list[i];
    while (!list.isEmpty())
    delete list.takeFirst();
    //scene->addItem(list[i]);
    }

    }
    }@

    Error:
    @Unhandled exception at 0x64dabd58 (QtGuid4.dll) in Chess.exe: 0xC0000005: Access violation reading location 0x00000059.@


  • Moderators

    As you remove items from the list, the list size decreases. When you remove list[0], list[1] becomes the new list[0]. So, in your case, since you're overrunning the bounds of your list because when you increment i, you're really skipping over an item.

    Try using a QMutableListIterator to walk the list. Or, at very least, take items from the end of your list, not the beginning.



  • I don´t have time to try it now, but what did you say is true only particularly. If I use only delete list[i] (for clear instead while (!list.isEmpty()) \ delete list.takeFirst();(which is in this cycle maybe even worse idea) which doesn´t work either).

    I have for example 5 object in list. 2nd (i=1) is movable so it is delete. Cycle end I increase (i=2) and compare (i < 4 (now I have 4 object)). So I omitted one object, but this is no reason for this kind of mistake. And if I´m at the end of list (we can except that other item aren´t movable) so i=3 compare i<4 and last item is movable so I delete 4th item, end the cycle, increase i (i=4) and compare (i<3) which return fail and cycle end. So you´re right I have this error in code, but this, I thing, shouldn´t cause this kind of error.

    I wrote it in hurry (I have to go out) so I hope it is clear (my English is not so good). But I will try what you wrote later.



  • The code is completely wrong. It deletes the complete list if it ever gets into the if branch!

    This is the harmful snippet:
    @
    while (!list.isEmpty())
    delete list.takeFirst();
    @

    I just have to agree to mlong:
    If you modify the list while iterating over it, a QMutableListIterator is a good approach. As an alternative, iterate from the end, as this does not change the indexes of the yet unvisited items.



  • 2Volker: You´re right.
    I tried these four different approaches. I don´t know what´s wrong:

    1: There I´m trying to use QMutableListIterator:

    @void MainWindow::deleteFigure()
    {

    QList<QGraphicsItem *> list = scene->items();

    QMutableListIterator<QGraphicsItem *> i(list);
    while (i.hasNext())
    {
    QGraphicsItem * val = i.next();
    if (val->flags() & val->ItemIsMovable)
    {
    i.remove();
    scene->removeItem(val);
    delete val;
    }
    }
    }@

    2:

    @void MainWindow::deleteFigure()
    {

    QList<QGraphicsItem *> list = scene->items();

    for (int i=0;i<list.count();i++) //list of graphics object
    {
    if (list[i]->flags() & list[i]->ItemIsMovable)
    {
    scene->removeItem(list[i]);
    value = list[i];
    list.removeAt(i);
    delete value;

    //scene->addItem(list[i]); //there I tried if items are really there
    //if I comment “delete value;“
    }

    }
    }@

    3: Iteration from end

    @void MainWindow::deleteFigure()
    {

    QList<QGraphicsItem *> list = scene->items();

    QGraphicsItem * value;
    for (int i=list.count();i>0;i--) //list of graphics object
    {
    if (list[i]->flags() & list[i]->ItemIsMovable)
    {
    scene->removeItem(list[i]);
    value = list[i];
    list.removeAt(i);
    delete value;
    }

    }

    }@

    4: There I delete more than I want, but it still doesn´t work

    @void MainWindow::deleteFigure()
    {

    QList<QGraphicsItem *> list = scene->items();
    while (!list.isEmpty())
    delete list.takeFirst();

    }@

    Error is the same everywhere:

    @Unhandled exception at 0x64dabd58 (QtGuid4.dll) in Chess.exe: 0xC0000005: Access violation reading location 0x00000059.@

    How I create object (maybe there is error? But everything works except delete):

    @graphicsSvgItem *svgItem = new graphicsSvgItem("...");
    svgItem->setFlags(QGraphicsRectItem::ItemIsSelectable);
    svgItem->setFlags(QGraphicsRectItem::ItemIsMovable);
    connect(svgItem, SIGNAL(xChanged()),
    this, SLOT(figureMoves()));
    connect(svgItem, SIGNAL(yChanged()),
    this, SLOT(figureMoves()));

    scene->addItem(svgItem);@

    graphicsSvgItem is my class:

     @ class graphicsSvgItem : public QGraphicsSvgItem@
    


  • I probably solved it. I just didn´t think. I had call function which should delete the object from this object itself! Something like:

    @void myobject::function()
    {
    deleteMe();
    }@

    It was little bit more complicated but in principle the same. Now my program fails because another error ( :) ). So I cannot be 100% sure (for now) that error will not appear later. But I think it will not. Function deleteLater () it probably solved it now.
    If I were copy whole source code (or best the wrong part) you could help me more…



  • Now I think, I can be entirely sure.


  • Moderators

    In your section 3: Iteration from end above, you have the line:
    @
    for (int i=list.count();i>0;i--) //list of graphics object
    @

    This will give you a bounds overrun when you try to access list[list.count()].

    In that case, you should use:
    @
    for (int i=list.count()-1; i>=0; i--) //list of graphics object
    @



  • I have to say you´re right - thank you.


Log in to reply
 

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