Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get mouse hover events for shapes with a hole in a QGraphicsItem?

I have a QGraphicsPathItem in Qt (using the PySide bindings in Python) where there is a big rectangle and a smaller rectangle inside. Because of the default filling rule (Qt.OddEvenFill) the inner rectangle is transparent. This effectively draws a shape with a hole.

Now I want to listen to mouse events like enter, leave, click, ... My simple approach of implementing hoverEnterEvent, .. of QGraphicsItem does not create mouse events when moving over the hole because the hole is still part of the item even if it is not filled.

I want to have a QGraphicsItem derivative that displays a custom shape whose outline is defined by a QPainterPath or one or several polygons and that can have holes and when the mouse enters a hole this is regarded as outside of the shape.

Example shape with a hole (when the mouse is in the inner rectangle it should be regarded as outside of the shape and mouse leave events should be fired):

Shape with a hole

However the solution should also work for arbitrary shapes with holes.

Example code in PySide/Python 3.3

from PySide import QtCore, QtGui

class MyPathItem(QtGui.QGraphicsPathItem):

    def __init__(self):
        super().__init__()
        self.setAcceptHoverEvents(True)

    def hoverEnterEvent(self, event):
        print('inside')

    def hoverLeaveEvent(self, event):
        print('outside')

app = QtGui.QApplication([])

scene = QtGui.QGraphicsScene()
path = QtGui.QPainterPath()
path.addRect(0, 0, 100, 100)
path.addRect(25, 25, 50, 50)

item = MyPathItem()
item.setPath(path)
item.setBrush(QtGui.QBrush(QtCore.Qt.blue))

scene.addItem(item)

view = QtGui.QGraphicsView(scene)
view.resize(200, 200)
view.show()

app.exec_()
like image 755
Trilarion Avatar asked Oct 20 '22 22:10

Trilarion


1 Answers

It seems that method shape from QGraphicsItem by default returns the bounding rectangle. Its returned path is used to determine if a position is inside or outside of a complex shape. However in case of a QGraphicsPathItem we already have a path and returning this instead of the bounding rectangle could solve the problem. And to my surprise it does.

Just add these two lines to the QGraphicsPathItem derivative from the question.

def shape(self):
    return self.path()
like image 99
Trilarion Avatar answered Oct 22 '22 11:10

Trilarion