The default mouseEvent
function in QGraphicsScene
allows to move the Item by press-and-hold, move, and release. I am trying to overwrite the QGraphicsScene mouseEvent()
function to accomplish the same movement with press-and-release-once (pick item), move (without holding press), press-and-release-twice (drop item). I though it would be as simple as:
self.moving = False
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
if self.moving == False: # first click, pick up, start moving
super().mousePressEvent(event)
self.moving = True
else: # second click, drop, end moving item
super().mouseReleaseEvent(event)
self.moving = False
def mouseMoveEvent(self, event):
if self.moving == True:
super().mousePressEvent(event)
super().mouseMoveEvent(event)
def mouseReleaseEvent(self, event):
pass
I am not able to pick up and move the item so far, does anyone spot anything wrong? Also, where can I find the original implementation of the QGraphicsScene mouseEvent function
?
Thank you!
First of all, you shall never call the base implementation of an event handler with a wrong argument type.
Calling
mousePressEvent
using a mouse move event as its argument is conceptually wrong, and while it's generally not "dangerous" when done on graphics items, it usually causes a fatal crash when done on widgets.That said, if you want to follow the mouse upon mouse press and release, that obviously means that you have to change the "follow state" within the
mouseReleaseEvent()
handler, not themousePressEvent()
one.Furthermore, you must ensure that:
About the first point, generally speaking a widget (or graphics item) becomes the mouse grabber when any mouse button is pressed on it and until that button has been released. Becoming a mouse grabber means that all mouse events are dispatched to that item until it releases the mouse; since you want to be able to receive mouse events after releasing the mouse button, you have to explicitly grab (or ungrab) the mouse when the button is released.
In the following example I'm showing how to implement the above, and also providing support for items that are already movable (through the
ItemIsMovable
flag). Items that show the "Movable flag" text can also be moved while keeping the left button pressed, otherwise only the press/release support is provided for other items.Be aware that moving items based on mouse events has to consider the item transformations: the
pos()
of events is always mapped in local coordinates, so if you click on the top left corner of a rectangle and the item is rotated, you will always get that top left corner position. SincesetPos()
uses the parent coordinate system, we have to map those positions to the parent in order to achieve proper movement. This also means that complex transformations (considering the parent) could make things much more difficult, so be aware of that. For more complex scenarios, you might have to further implement the computation of the target position, or stick with the default behavior.