Search code examples
qtqgraphicsitemqgraphicssceneqmouseevent

Qt: change QGraphicsItem receiver during mouse move


I am currently trying to implement a Bezier pen tool. The course of events looks like this:

  • click on point (QGraphicsItem), start moving while clicked
  • in QGraphicsScene mouseMoveEvent, prevent moves of point (with a boolean flag) until when distance from point.pos() to event.scenePos() reaches a threshold. When this happens unselect and mouseRelease point, add a node (QGraphicsItem) – select it and give it mousePress state (plus unset the boolean flag)
  • the user can move node after that, then release mouse.

(The node is a child item of the point.)

I tried to do this inside the scene’s mouseMoveEvent (I have a conditional branch to know when to do this):

point.setSelected(False)
point.ungrabMouse()
node.setPos(event.scenePos()-point.pos()) # positioning relative to point since it’s a childItem()
node.grabMouse()
event.accept()

But after doing this it occured that the node was only getting mouseMoveEvent’s after I release the mouse… (I print them in the console, the node itself did not move.)

So I figured, maybe the scene needs to eat a mouseReleaseEvent before sort of "releasing focus". I found an article that is tangent to the subject here.

So then instead of using ungrabMouse()/grabMouse(), I tried this:

mouseRelease = QEvent(QEvent.MouseButtonRelease)
self.sendEvent(point, mouseRelease)
node.setPos(event.scenePos()-point.pos()) # positioning relative to point since it’s a childItem()
mousePress = QEvent(QEvent.MouseButtonPress)
self.sendEvent(node, mousePress)

Now when I reach the distance threshold, I can see that only point gets selected (good) however as I move further both point and node are selected and moving… I would expect that since I have unselected and released (parent) point, it would not keep moving.

The article I linked to does do something different but it says "It turns out, we have to simulate a mouse release event to clear Qt’s internal state." which might be relevant to the current situation however I do not know what extra steps might need to be taken in order to “clear Qt’s internal state”… so I’m hoping a QGraphics aficionado can weigh in and help me out figuring this.

Thanks for having a look here.


Solution

  • A combination of sending mouse events and grabbing mouse manually works… has to be ungrabbed manually on mouseRelease though.