Qt mouse event propagation with scene items

2019-09-16 17:09发布

When QGraphicsScene item is behind it's child Item, I wish for mouse grabber to check item behind, and then grab topmost item if the first is not grabbed.

SAMPLE CODE :

from PySide.QtCore import *
from PySide.QtGui import *

class View(QGraphicsView):
    pass
class Scene(QGraphicsScene):
    pass

class ChildCircle(QGraphicsEllipseItem):
    def __init__(self, parent):
        super(ChildCircle, self).__init__()
        self.setRect(QRect(-20,-20,70,70))
        self.setParentItem( parent )

    def mousePressEvent(self, event):
        print "Circle is Pressed", event.pos()

class ParentRectangle(QGraphicsRectItem):
    def __init__(self, scene):
        super(ParentRectangle, self).__init__()
        self.scene = scene
        self.setRect(QRect(0,0,20,20))
        self.scene.addItem(self)

        circle = ChildCircle(self)

    def mousePressEvent(self, event):
        print "Rectangle PRESS", event.pos()


class Window(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.s = Scene()
        self.s.setSceneRect(-200,-100,300,300,)

        self.v = View(self.s)
        self.v.setDragMode(QGraphicsView.ScrollHandDrag)
        self.setCentralWidget(self.v)

        ParentRectangle(self.s)

if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    window = Window()
    window.resize(300, 200)
    window.show()
    sys.exit(app.exec_())

标签: qt pyqt pyside
1条回答
祖国的老花朵
2楼-- · 2019-09-16 17:14

I am not sure I understand your question. The Qt's documentation clearly says the following about mousePressEvent method:

The mouse press event decides which item should become the mouse grabber. If you do reimplement this function, event will by default be accepted (see QEvent::accept()), and this item is then the mouse grabber. This allows the item to receive future move, release and doubleclick events. If you call QEvent::ignore() on event, this item will lose the mouse grab, and event will propagate to any topmost item beneath.

All you have to do it's to decide whether to call QEvent::ignore method or not. So, for example, if the circle object does always ignore mouse press event, the rectangle object will always be the mouse grabber (if you clicked on rectangle). In this code the mouse grabber is item you have clicked.

class ChildCircle(QGraphicsEllipseItem):
    def __init__(self, parent=None):
        super(ChildCircle, self).__init__(parent)
        self.setRect(QRect(-20,-20,70,70))
        self.setFlags(QGraphicsItem.ItemIsMovable)

    def mousePressEvent(self, event):
        # Ugly way to know there are items except self
        if len(self.scene().items(event.scenePos())) > 1:
            # Propogate the event to the parent
            event.ignore()

class ParentRectangle(QGraphicsRectItem):
    def __init__(self, scene, parent=None):
        super(ParentRectangle, self).__init__(parent)
        self.scene = scene
        self.setRect(QRect(0,0,20,20))
        self.scene.addItem(self)
        circle = ChildCircle(self)
        self.setFlags(QGraphicsItem.ItemIsMovable)

    def mousePressEvent(self, event):
        pass
查看更多
登录 后发表回答