1
votes

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.

1
Is mousetracking active on your widget? QWidget::setMouseTracking(true);Johannes Munk
@JohannesMunk Hi Johannes, maybe my post is not clear: what I am willing to do is essentially this: - click on point, start moving while clicked - in QGraphicsScene mouseMoveEvent, when distance from point to event.pos() reaches threshold, unselect and release point, spawn node – select it and give it mousePress state - the user can keep moving node after that, then release mouse. Is this all doable without having to use setMouseTracking(True)? I would like to essentially set the widget in mousePress state so I don’t have to always track mouse. Thanksblameless75
Why do you want to avoid mouseTracking?Johannes Munk
@JohannesMunk Because it is an additional, opt-in layer of functionality that I think can be achieved with release and press, no?blameless75
I doubt that you can do that. I never had any troubles with mouseTracking. To clarify: everything works fine, if you enable it?Johannes Munk

1 Answers

0
votes

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