3

I'd like to find out if a user hovers over or clicks a GraphicsScene shape object (for example, the ellipse object I commented below). I'm new to PyQt and the documentation is much better for C++ than Python, so I'm having a bit of trouble figuring this one out.

from PyQt4 import QtGui, QtCore

class MyFrame(QtGui.QGraphicsView):
    def __init__( self, parent = None ):
        super(MyFrame, self).__init__(parent)

        self.setScene(QtGui.QGraphicsScene())

        # add some items
        x = 0
        y = 0
        w = 45
        h = 45
        pen = QtGui.QPen(QtGui.QColor(QtCore.Qt.green))
        brush = QtGui.QBrush(pen.color().darker(150))

        # i want a mouse over and mouse click event for this ellipse
        item = self.scene().addEllipse(x, y, w, h, pen, brush)


        item.setFlag(QtGui.QGraphicsItem.ItemIsMovable)

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

Update!!!

Now I can get an event to take place based on a mouse click release. Unfortunately, only the last item I create can respond to events. What's going on here?

from PyQt4 import QtGui, QtCore

class MyFrame(QtGui.QGraphicsView):
    def __init__( self, parent = None ):
        super(MyFrame, self).__init__(parent)

        self.setScene(QtGui.QGraphicsScene())

        # add some items
        x = 0
        y = 0
        w = 20
        h = 20
        pen = QtGui.QPen(QtGui.QColor(QtCore.Qt.green))
        brush = QtGui.QBrush(pen.color().darker(150))

        # i want a mouse over and mouse click event for this ellipse
        for xi in range(10):
            for yi in range(10):
                item = callbackRect(x+xi*30, y+yi*30, w, h)
                item.setAcceptHoverEvents(True)
                item.setPen(pen)
                item.setBrush(brush)
                self.scene().addItem(item)

        # item = self.scene().addEllipse(x, y, w, h, pen, brush)


        item.setFlag(QtGui.QGraphicsItem.ItemIsMovable)

class callbackRect(QtGui.QGraphicsRectItem):
    '''
    Rectangle call-back class.
    '''

    def mouseReleaseEvent(self, event):
        # recolor on click
        color = QtGui.QColor(180, 174, 185)
        brush = QtGui.QBrush(color)
        QtGui.QGraphicsRectItem.setBrush(self, brush)

        return QtGui.QGraphicsRectItem.mouseReleaseEvent(self, event)

    def hoverMoveEvent(self, event):
        # Do your stuff here.
        pass

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

Screen shot of only last item created being 'eventable'.

nick_name
  • 1,353
  • 3
  • 24
  • 39

1 Answers1

3

You can define your own ellipse class and replace both click and hover events:

class MyEllipse(QtGui.QGraphicsEllipseItem):

    def mouseReleaseEvent(self, event):
        # Do your stuff here.
        return QtGui.QGraphicsEllipseItem.mouseReleaseEvent(self, event)

    def hoverMoveEvent(self, event):
        # Do your stuff here.
        pass

Usage:

item = MyEllipse(x, y, w, h)
item.setAcceptHoverEvents(True)
item.setPen(pen)
item.setBrush(brush)
self.scene().addItem(item)

Hope it helps!

cdonts
  • 9,304
  • 4
  • 46
  • 72
  • Thanks! This is really useful. Unfortunately, when I integrate that with my code, it compiles/interprets fine, but nothing happens when I mouseover or click the ellipse item. It seems like the class MyEllipse doesn't receive the signal from the graphics view-->graphics scene. Any ideas? – nick_name Jan 06 '16 at 12:59
  • Okay, I got it to link properly. Unfortunately, I tried creating ellipses in a for loop and it seems that only the last created object can receive an event call. Any ideas? (I've updated the question with code). – nick_name Jan 06 '16 at 13:21
  • `item.setFlag(QtGui.QGraphicsItem.ItemIsMovable)` should go inside the for loop, before `addItem`. Otherwise only the last item will be movable! – cdonts Jan 06 '16 at 15:57