13

In my application I want to use QGraphicsItemGroup for grouping items into one item.
I played with it a little and not sure using it because when I want to catch events, events are merged together but I want to handle specific event with specific child.
How can I achieve this?

onurozcelik
  • 1,214
  • 3
  • 21
  • 44

3 Answers3

15

You need to call QGraphicsItemGroup::setHandlesChildEvents(false). This stops the QGraphicsItemGroup trying to handle the event, and lets the child QGraphicsItems handle them instead.

Whatang
  • 9,938
  • 2
  • 22
  • 24
5

I think that's the point of the QGraphicsItemGroup. Judging from the documentation, this is meant to simplify moving and transforming multiple items at once e.g. imagine the following case: a user draws a selection rectangle around several items in an application because he wants to move all of them. Perhaps what you want more is to create a hierarchy of items, e.g. have one parent item with several child items. This way you'll get the individual events for each item. This can be accomplished by calling QGraphicsItem::setParentItem();

humbagumba
  • 2,054
  • 15
  • 16
  • 4
    Every time i have tried to use QGraphicsItemGroup I went back to the plain parent child relationships. The documentation is not very clear on it – Harald Scheirich Jun 11 '10 at 13:11
0

The question doesn't specify which version of Qt is concerned and there is a correct answer for Qt4. Here is an answer for Qt5 (it works for PyQt5 and I guess it'll work also in C++). The solution was to reimplement sceneEvent, reimplementing a specialized event-catcher such as contextMenuEvent was not sufficient.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from PyQt5 import QtCore
from PyQt5 import QtGui
from PyQt5 import QtWidgets


class GraphicsItem(QtWidgets.QGraphicsItem):
    def __init__(self,
               rect: QtCore.QRectF,
               name: str,
               parent: QtWidgets.QGraphicsItem = None):
        super().__init__(parent)
        self._name = name
        self._rect = rect

    def boundingRect(self):
        return self._rect

    def paint(self,
              painter: QtGui.QPainter,
              option: QtWidgets.QStyleOptionGraphicsItem,
              widget: QtWidgets.QWidget = None):
        painter.setPen(QtGui.QPen(QtCore.Qt.NoPen))
        painter.setBrush(QtGui.QBrush(QtCore.Qt.red))
        painter.drawRect(self._rect)

    def sceneEvent(self, event: QtCore.QEvent):
        if (event.type() == QtCore.QEvent.GraphicsSceneContextMenu):
            self.contextMenuEvent(event)
        event.accept()
        return True

    def contextMenuEvent(self, event: QtWidgets.QGraphicsSceneContextMenuEvent):
        print(f'contextMenuEvent in "{self._name}"')


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()

        self._scene = QtWidgets.QGraphicsScene()

        layout = QtWidgets.QHBoxLayout()
        self._view = QtWidgets.QGraphicsView(self._scene)
        layout.addWidget(self._view)

        self._widget = QtWidgets.QWidget()
        self._widget.setLayout(layout)

        group = QtWidgets.QGraphicsItemGroup()
        self._scene.addItem(group)

        scene_item = GraphicsItem(QtCore.QRectF(0, 0, 100, 100), 'in scene')
        self._scene.addItem(scene_item)

        group_item = GraphicsItem(QtCore.QRectF(150, 0, 100, 100), 'in group')
        group.addToGroup(group_item)

        group_item = GraphicsItem(QtCore.QRectF(300, 0, 100, 100), '2nd in group')
        group.addToGroup(group_item)

        self.setCentralWidget(self._widget)
        self.setWindowTitle('contextMenuEvent with QGraphicsItemGroup')


if __name__ == '__main__':
    import sys

    app = QtWidgets.QApplication(sys.argv)

    mainWindow = MainWindow()
    mainWindow.setGeometry(100, 100, 800, 500)
    mainWindow.show()

    sys.exit(app.exec_())