banjo bill
banjo bill

Reputation: 33

How to avoid mouse events being eaten by QGraphicsView

I want mouse events to reach the appropriate QGraphicsItem but they get no further than the QGraphicsView.

I have reduced my code to 41 lines, commented out event handlers but to no avail. It is either handled by QGraphicsView if that has a handler or, if not, is not caught at all.

I'm sure I'm missing something obvious but I can't see it.

from PyQt5.QtWidgets import *

class MyFrame(QGraphicsView):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setScene(QGraphicsScene())
        self.scene().addItem(Group())

    def mouseReleaseEvent(self, event):
        print('in QGraphicsView')
        return QGraphicsView.mouseReleaseEvent(self, event)

class Group(QGraphicsItemGroup):
    def __init__(self, parent=None):
        super().__init__()

        item = MyEllipse(0, 0, 20, 20)
        self.addToGroup(item)

    def mouseReleaseEvent(self, event):
        print('in QGraphicsItemGroup')
        return QGraphicsItemGroup.mouseReleaseEvent(self, event)

class MyEllipse(QGraphicsEllipseItem):
    def mouseReleaseEvent(self, event):
        print('in QGraphicsEllipseItem')
        return QGraphicsEllipseItem.mouseReleaseEvent(self, event)

if __name__ == '__main__':
    app = QApplication([])
    f = MyFrame()
    f.show()
    app.exec_()

Upvotes: 1

Views: 195

Answers (1)

eyllanesc
eyllanesc

Reputation: 243955

mouseReleaseEvent is called if and only if the event that the mousePressEvent handles is accepted, so with the following code the event will arrive at QGraphicsItemGroup:

class Group(QGraphicsItemGroup):
    def __init__(self, parent=None):
        super().__init__()

        item = MyEllipse(0, 0, 20, 20)
        self.addToGroup(item)

    def mousePressEvent(self, event):
        QGraphicsItemGroup.mousePressEvent(self, event)
        event.accept()

    def mouseReleaseEvent(self, event):
        print('in QGraphicsItemGroup')
        QGraphicsItemGroup.mouseReleaseEvent(self, event)

But as @ekhumoro points out, the QGraphicsItemGroup acts as a single element so events are not transported to the items they handle.

If you want to detect when the item is pressed you can use the following method:

class Group(QGraphicsItemGroup):
    def __init__(self, parent=None):
        super().__init__()

        self._item = MyEllipse(0, 0, 20, 20)
        self.addToGroup(self._item)

    def mousePressEvent(self, event):
        QGraphicsItemGroup.mousePressEvent(self, event)
        event.accept()

    def mouseReleaseEvent(self, event):
        print('in QGraphicsItemGroup')
        if self._item.mapToParent(self._item.boundingRect()).containsPoint(event.pos(), Qt.OddEvenFill):
            print("_item")
        QGraphicsItemGroup.mouseReleaseEvent(self, event)

Upvotes: 1

Related Questions