Graphics scene crash
-
Background info:
I have some custom graphics items that inherits from BaseItem (parent = QGraphicsItem). One of the property of BaseItem is groupId with getter and setter methods. I've implemented the rubberband to select items on the scene. Because some items belong to a group (via groupId) I want ALL items in a group to be selected if one or more of the item in that group is selected; I'm not using QGraphicsItemGroup because it doesn't fit what I want to do. Selection of items using the rubberband works. In order to select the other items (not in the selection area of the rubberband but belong to the selected group) I've wrote the following blocks of code:// BLOCK 1 QStringList groupIds; QList<QGraphicsItem*> selectedItems = scene()->selectedItems(); foreach (QGraphicsItem *item, selectedItems) { BaseItem *baseItem = qgraphicsitem_cast<BaseItem*>(item); QString groupId = baseItem->getGroupId(); bool found = false; foreach (QString gId, groupIds) { if (gId == groupId) { found = true; break; } } if (!found) { groupIds.append(groupId); } } // BLOCK 2 QList<QGraphicsItem*> items = scene()->items(); foreach (QGraphicsItem *item, items) { BaseItem *baseItem = qgraphicsitem_cast<BaseItem*>(item); QString groupId = baseItem->getGroupId(); foreach (QString gId, groupIds) { if (groupId == gId) { item->setSelected(true); break; } } } // CRASH here (never get to this point even though reach end of loop ie. all items were processed)
The program just crash. No error message. Using qDebug I was able to see BLOCK 2 is the problem. If I comment BLOCK 2, program execute fine. I'm new to qt so have no idea what's going on; guessing it has something to do with QGraphicsScene, but have no info to go on. Searching around there's mention of calling prepareGeometryChange() but that does not help me here. Perhaps someone can spot something that I'm doing wrong. Thanks a million.
-
Background info:
I have some custom graphics items that inherits from BaseItem (parent = QGraphicsItem). One of the property of BaseItem is groupId with getter and setter methods. I've implemented the rubberband to select items on the scene. Because some items belong to a group (via groupId) I want ALL items in a group to be selected if one or more of the item in that group is selected; I'm not using QGraphicsItemGroup because it doesn't fit what I want to do. Selection of items using the rubberband works. In order to select the other items (not in the selection area of the rubberband but belong to the selected group) I've wrote the following blocks of code:// BLOCK 1 QStringList groupIds; QList<QGraphicsItem*> selectedItems = scene()->selectedItems(); foreach (QGraphicsItem *item, selectedItems) { BaseItem *baseItem = qgraphicsitem_cast<BaseItem*>(item); QString groupId = baseItem->getGroupId(); bool found = false; foreach (QString gId, groupIds) { if (gId == groupId) { found = true; break; } } if (!found) { groupIds.append(groupId); } } // BLOCK 2 QList<QGraphicsItem*> items = scene()->items(); foreach (QGraphicsItem *item, items) { BaseItem *baseItem = qgraphicsitem_cast<BaseItem*>(item); QString groupId = baseItem->getGroupId(); foreach (QString gId, groupIds) { if (groupId == gId) { item->setSelected(true); break; } } } // CRASH here (never get to this point even though reach end of loop ie. all items were processed)
The program just crash. No error message. Using qDebug I was able to see BLOCK 2 is the problem. If I comment BLOCK 2, program execute fine. I'm new to qt so have no idea what's going on; guessing it has something to do with QGraphicsScene, but have no info to go on. Searching around there's mention of calling prepareGeometryChange() but that does not help me here. Perhaps someone can spot something that I'm doing wrong. Thanks a million.
@Lyri1014 If your application crashes the first thing to do is to run it in debugger and check the stack trace to see where exactly it crashes.
One cause for the crash could be the fact that you're not checking baseItem pointer - it will be nullptr if the cast failed.
-
@Lyri1014 If your application crashes the first thing to do is to run it in debugger and check the stack trace to see where exactly it crashes.
One cause for the crash could be the fact that you're not checking baseItem pointer - it will be nullptr if the cast failed.
Thanks for your reply. I did add the code to check for the cast pointer but still same problem. Also, all graphics items on the scene inherit from BaseItem, so a check is not really needed. The weird thing is that I can easily loop through the selected items in BLOCK 1 without any problem. Seems like looping through all items in the scene is the cause; when it reaches the end of all items it crashes.
After some dissecting of my code. I found that there are an additional item in the scene when calling scene->items(). I don't know what this item is but that's what causing the crash. In one test, I know from my code that there are only 6 items but the items.size() return 7. By using a for loop with size - 1 everything works as intended. Not sure what the last item but I'll find out; feels kinda silly now. Thanks.
-
-
Thanks for your reply. I did add the code to check for the cast pointer but still same problem. Also, all graphics items on the scene inherit from BaseItem, so a check is not really needed. The weird thing is that I can easily loop through the selected items in BLOCK 1 without any problem. Seems like looping through all items in the scene is the cause; when it reaches the end of all items it crashes.
After some dissecting of my code. I found that there are an additional item in the scene when calling scene->items(). I don't know what this item is but that's what causing the crash. In one test, I know from my code that there are only 6 items but the items.size() return 7. By using a for loop with size - 1 everything works as intended. Not sure what the last item but I'll find out; feels kinda silly now. Thanks.
@Lyri1014 said in Graphics scene crash:
I did add the code to check for the cast pointer but still same problem.
Then please edit your code to show what you did. You sound like a competent programmer, but after years of helping here I know that if people want help we need to see actual code, not be told alterations have been made and they are fine!
Which line makes it "crash"? If you empty out the body of BLOCK 2 so it does nothing other than
foreach (QGraphicsItem *item, items) {}
or equivalent does it still crash? Since you say there is an extra item which you are not sure about, break in debugger and try looking intoitem
directly, do you get any clues as to what it is? -
Thanks for your reply. I did add the code to check for the cast pointer but still same problem. Also, all graphics items on the scene inherit from BaseItem, so a check is not really needed. The weird thing is that I can easily loop through the selected items in BLOCK 1 without any problem. Seems like looping through all items in the scene is the cause; when it reaches the end of all items it crashes.
After some dissecting of my code. I found that there are an additional item in the scene when calling scene->items(). I don't know what this item is but that's what causing the crash. In one test, I know from my code that there are only 6 items but the items.size() return 7. By using a for loop with size - 1 everything works as intended. Not sure what the last item but I'll find out; feels kinda silly now. Thanks.
@Lyri1014 said in Graphics scene crash:
Thanks for your reply. I did add the code to check for the cast pointer but still same problem. Also, all graphics items on the scene inherit from BaseItem, so a check is not really needed. The weird thing is that I can easily loop through the selected items in BLOCK 1 without any problem. Seems like looping through all items in the scene is the cause; when it reaches the end of all items it crashes.
After some dissecting of my code. I found that there are an additional item in the scene when calling scene->items(). I don't know what this item is but that's what causing the crash. In one test, I know from my code that there are only 6 items but the items.size() return 7. By using a for loop with size - 1 everything works as intended. Not sure what the last item but I'll find out; feels kinda silly now. Thanks.
Hi,
It sounds like an off by one error.
Out of curiosity, how did you write that loop ?
-
@Lyri1014 said in Graphics scene crash:
Thanks for your reply. I did add the code to check for the cast pointer but still same problem. Also, all graphics items on the scene inherit from BaseItem, so a check is not really needed. The weird thing is that I can easily loop through the selected items in BLOCK 1 without any problem. Seems like looping through all items in the scene is the cause; when it reaches the end of all items it crashes.
After some dissecting of my code. I found that there are an additional item in the scene when calling scene->items(). I don't know what this item is but that's what causing the crash. In one test, I know from my code that there are only 6 items but the items.size() return 7. By using a for loop with size - 1 everything works as intended. Not sure what the last item but I'll find out; feels kinda silly now. Thanks.
Hi,
It sounds like an off by one error.
Out of curiosity, how did you write that loop ?
A little background on the program I'm working on. The program allow the user to analyze a video frame by frame (if so chooses) and provide various tools such as measuring angles within a video frame. The mistake I made was I forgot about the image background (ie. frame image) within the scene; that's the extra item that I didn't account for. Probably because I've been looking at it for so long it completely escapes my mind. Because scene->items() return items in descending order and I'm not interested in the background image, I can simply ignore the last item. It was a simple mistake by me but it caused me some grief for a while. Because I'm new to qt and c++ I kind of panic a bit and looked into different possible causes rather than reassessing my assumptions.
-
A little background on the program I'm working on. The program allow the user to analyze a video frame by frame (if so chooses) and provide various tools such as measuring angles within a video frame. The mistake I made was I forgot about the image background (ie. frame image) within the scene; that's the extra item that I didn't account for. Probably because I've been looking at it for so long it completely escapes my mind. Because scene->items() return items in descending order and I'm not interested in the background image, I can simply ignore the last item. It was a simple mistake by me but it caused me some grief for a while. Because I'm new to qt and c++ I kind of panic a bit and looked into different possible causes rather than reassessing my assumptions.
@Lyri1014
I assume you meanBaseItem *baseItem = qgraphicsitem_cast<BaseItem*>(item);
returnednullptr
. You should always check runtime casts, even if just with aQ_ASSERT()
.When you have used
QGraphics
stuff for a while, you may find usingdarwBackground()
for a image scene background is more convenient than creating it as aQGraphicsItem
.