0

I create several subclassed QGraphicRectItems with parent/child relationships to keep them in lock step on the screen. For whatever reason, the hover events on the children are triggering the parent hover event, but I want all of the instances' hover events to be independent. Is there any way to keep this from happening? Does an independent event filter need to be used? Strangely, adding the parent item to the scene after the children makes the hover events independent, but then the motion is wrong if the parent is moved.

Here is a MWE:

import sys
from PyQt5 import QtCore, QtWidgets, QtGui

# Define a hoverable rectangle item to be used by the DefinitionGraphic
class HoverRectItem(QtWidgets.QGraphicsRectItem):

    # Initialize
    def __init__(self, x, y, width, height,
                 parent = None,
                 fill = QtCore.Qt.blue,
                 highlight = QtCore.Qt.red,
                 name = ''):
        super().__init__(x, y, width, height, parent = parent)

        # Set fill and highlight colors
        self.fill_brush = QtGui.QBrush(QtGui.QColor(fill))
        self.hover_brush = QtGui.QBrush(QtGui.QColor(highlight))
        self.setBrush(self.fill_brush)
        self.name = name

        # Enable hover events
        self.setAcceptHoverEvents(True) 

    # Define the Hover Event
    def hoverEnterEvent(self, event):
        print(self.name+" hover enter")
        self.setBrush(self.hover_brush)
        self.update()
        super().hoverEnterEvent(event)

    # Define the Hover Leave Event
    def hoverLeaveEvent(self, event):
        print(self.name+" hover leave")
        self.setBrush(self.fill_brush)
        self.update() 
        super().hoverLeaveEvent(event)

# Main
if __name__ == "__main__":

    # Initialize the app
    app = QtWidgets.QApplication(sys.argv)

    # Create the scene
    scene = QtWidgets.QGraphicsScene()

    # Create rectangles
    central_rect = HoverRectItem(0, 0, 100, 50, parent = None, name = 'central')
    scene.addItem(central_rect)
    central_rect.setFlags(QtWidgets.QGraphicsItem.ItemIsMovable)
    input_rect = HoverRectItem(-30, 0, 20, 50, parent = central_rect, name = 'input')
    scene.addItem(input_rect)
    output_rect = HoverRectItem(110, 0, 20, 50, parent = central_rect, name = 'output')
    scene.addItem(output_rect)

    # Create the view and show
    view = QtWidgets.QGraphicsView(scene)
    view.setWindowTitle("QGraphicsItem Hover Example")
    view.show()
    app.exec_()
3
  • First of all, if you explicitly add items to a scene, they are no longer children of the parent you've used: check the output of output_rect.parent(). For the same reason, you should not add a child to the scene, as it's implicitly added when the parent is (check the output in a terminal or prompt and you'll see a warning). That said, graphics scene hover events follow the (QHoverEvent logic. If you only want to react when a hover event is exactly within the item boundaries, then simply check if the event.pos() is within the boundingRect(). Commented Oct 3 at 16:14
  • @musicmante Agh, I have been messing with this so much I forgot the explicit adds. Yea, so I had thought about the position check, but that seems like a messy workaround and I was hoping for better. Looking around, it seems as though the hover events are passed regardless of any event.accept() etc. Commented Oct 3 at 16:39
  • As noted above, the logic is the same as in QHoverEvent (which states in the documentation that the propagation always happens regardless whether the event is accepted or not). Hover enter events are always dispatched to parents (with panel items being the "top level limit"), so you either check the bounding rect (or the shape for non rectangular items), or you apply the changes in the hoverMoveEvent. Commented Oct 3 at 21:39

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.