Like other primitives in Qt, QGraphicsItems can handle mouse events and the like. Sweet! Now say I need for an event on one QGraphicsItem to be propagated to some other QGra
I suggest B unless you have relatively few QGraphicsItems. I believe QGraphicsItems are not QObjects because there is a certain amount of overhead associated with QObjects. The QGraphicsView framework was designed to allow fast insertion and deletion of many (e.g., thousands) QGraphicsItems into a scene, so a lighter-weight approach was preferred.
I would look to the concept of parenting in QGraphicsItems. QGraphicsItems can have parents and children, and this has several effects similar to parenting amongst QObjects. For example, if you move a parent QGraphicsItem, its children will move with it, and if you delete a parent, its children will be deleted. You can access a QGraphicsItem's parent using QGraphicsItem::parentItem()
, and children using QGraphicsItem::childItems()
. So, you can easily access sibling items like this:
QList<QGraphicsItem *> mySiblings = this->parentItem()->childItems();
Note that mySiblings
includes this
.
Signaling is not part of QGraphicItem because they do not inherit from QObjects. This was a design decision for performance reasons, to allow very large and fast scenes. If you decide you really need special cases for signals, QGraphicsWidget was created to fill this gap. It does inherit from QObject and lets you have a mixture of QWidget and QGraphicsItem functionality. Though it is recommended that you avoid this if your scenes are even moderately sizable.
Another option which might be relevant to your situation is to make use of the sceneEventFilter method. You can set one item to receive events for another and decide if they should be propagated or not:
http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/qgraphicsitem.html#sceneEventFilter
One item can be set as the filter for multiple objects. And it can identify each individual item and event to respond to.
Generally though you should make use of the scene for coordination across its objects. That is already the pattern being used for events (the scene coordinating delivery of all events to the items).
Also, it seems that your option A is not possible because QGraphicsItem does not even have an emit method. You would need to compose a QObject instance inside it as a member and use that to emit signals. Something along the lines of myItem.qobject.emit()
. Otherwise, you would have to inherit your own completely custom one from QGraphicsObject
Update 1: Addressing your main comment update
Your specific situation is a rectangle with "hot corners". I would see this being a custom QGraphicsItem. You would probably subclass QGraphicsRectItem, and then compose the child hot corner items inside as children items (setParentItem()
). Now your rectangle item knows about its children and can act on them directly. You could set the rectangle item to be the sceneEventFilter for the children and handle their events directly. No need to go back up to the scene. Let all this logic live in the class.
Update 2: Addressing your added question #3
Propagating communications up beyond the scene to QWidget's has a couple approaches I can think of:
graphicsRect.resizedCallback
as an attribute, or a setter graphicsRect.setResizedCallback(cbk)
. In your rect class, you would just call that when appropriate. If the callback it set, it can be used to call something on your scene directly. The rect class still has no knowledge of that logic. It just calls a callback.Those are just some suggestions. I'm sure there are other ways.