2

I am using the QGraphicsScene in Qt5 to add different QGraphicsItems. Some of them have further child items, some not. But now I need the possibility to find all top-level items. Surely, I could write a method, which would use the QList<QGraphicsItem *> QGraphicsScene::items(...) const method and then iterating through the returned list, looking for all items, that would return 0 as their parent. But probably the returned list will be long with only very few top-level items.

So, is there any better solution?

quarenjo
  • 47
  • 7
  • 2
    You would need to maintain a list yourself, as you add items to a scene and parent them. – TheDarkKnight Oct 30 '14 at 09:06
  • "But probably the returned list will be long...". How large can it be? If several dozens - it will not be a problem to iterate over them in terms of performance, I think. – vahancho Oct 30 '14 at 09:21
  • @vahancho As I need to display points on curves and the curves may be big and may have lots of points and there may be several curves... the number of objects increases rapidly. Therefore I don't think it's a good idea to cycle through every little point. – quarenjo Oct 30 '14 at 12:33
  • @quarenjo `QGraphicsScene::items()` returns the items sorted by depth IIRC, so you can cycle through the items until the parent isn't null. You can also use overloads of the method that sort alphabetically by name. You could setup a nomenclature that identifies top level items. – Félix Cantournet Oct 30 '14 at 12:40
  • cf qt docs for `QGraphicsScene::items()` : "Returns a list of all items in the scene in descending stacking order." – Félix Cantournet Oct 30 '14 at 12:41

2 Answers2

0

I'd try with:

QGraphicsItem * QGraphicsItem::topLevelItem () const

because in most practical situations, there is only one top-level item. Otherwise you need to go with one of the items() methods. If you choose the descending sort order, you can stop iterating as soon as you find that an item has a parent.

user1095108
  • 14,119
  • 9
  • 58
  • 116
  • As the user of the application can decide how many top level items may be positioned in the GraphicsScene, I probably will have more than just one. But the idea is good. Maybe it's best to use one (fake) item without any display. Then I only would have to call `childItems()` on this fake item, to get the real top level items. – quarenjo Nov 01 '14 at 21:33
  • @quarenjo I wrote the answer as I did, because the Qt's Graphics framework is usually used alongside Qt Quick 1, which only allows a single root item to be instantiated. Of course you could fiddle a little and insert your own top-level item(s), but it is rare. Also, perhaps stay clear of the Graphics framework as it is obsolescent. Look into Qt Quick 2 and the new scene graph API also. – user1095108 Nov 01 '14 at 21:55
  • Actually I don't use any version of Qt Quick and wasn't aware that it is more normal to use the Qt's Graphics framework with some sort of Qt Quick, than without it. Do you know if it is also obsolescent to use it without Qt Quick? Up to now I couldn't find anything which points to that. So hopefully it will remain. – quarenjo Nov 05 '14 at 12:16
  • Yeah, it is obsolescent to use the Graphics framework directly or through Qt Quick 1. After all, the Graphics framework preceded and inspired Qt Quick 1 and now Qt is moving beyond it, the scene graph API and Qt Quick 2 are the contemporary things. It will remain for the lifetime of Qt5, beyond that I don't know. – user1095108 Nov 05 '14 at 13:09
  • Is there some official statement indicating the QGraphicsScene/QGraphicsView is obsolete and may be removed? It's important for my project(s), and we're not using Qt Quick, nor have any plans to move to it. – goug Oct 01 '16 at 00:04
-1

DIT : The method QGraphicsScene::items() returns the items sorted by depth IIRC, so you can cycle through it until the parent isn't null. This should be linear with regards to the number of top level items which is probably the best you can do.

it appears I was mistaken, this method returns the items sorted depth-first which is the opposite of what we want.

However there are also overloads that allow you to sort them by name.

I suggest you use nomenclature to identify all top-level item (say all their names start with "__top") You can then loop while (name.startsWith("__top"))

Félix Cantournet
  • 1,941
  • 13
  • 17
  • I read the "Returns a list of all items in the scene in descending stacking order." in the Qt docs, but wasn't sure, (may sound stupid) what exactly is meant with "stacking order". So I tested it. It seems to be a depth first sorting => starts with a top-level item, lists a child, and the child-child... then the next top-level item... So that won't be helpful. But the naming of the QGraphicItems is maybe a solution. – quarenjo Oct 30 '14 at 16:44
  • QGraphicsItem does not inherit from QObject and can't be found, that's the problem with your second approach. – user1095108 Oct 31 '14 at 11:10
  • True. it works for a QDeclarativeView & QDeclarativeItem. I though it would for QGraphicsView too. – Félix Cantournet Oct 31 '14 at 11:24