Detect when QGraphicsItem dropped
-
@JonB said in Detect when QGraphicsItem dropped:
With the QGraphicsItem::ItemIsMovable flag set, when it allows you to drag a QGraphicsItem around, is that "drag and drop"?
I don't think so... that's why I wrote my comment above...
ItemIsMovable
andQDrag
/QDrop
are two different pair of shoes. The latter occures when dragging an item from another place to the scene (or from one scene to another). -
@Pl45m4 Absolutely, just got that, your post crossed with my update. Will investigate tomorrow.
-
I will still have to recognise this is the release at the of an item-move, not e.g. just a click, and which item has been moved.... Seems a shame, I was expecting/hoping for something like an event at the end of the item move, with the
QGraphicsItem
moved as an argument.It seems so simple: I just moved an item I set
ItemIsMovable
on, could you tell me which item just finished getting moved? Mine cannot be the only application which needs to act on that! -
I will still have to recognise this is the release at the of an item-move, not e.g. just a click, and which item has been moved.... Seems a shame, I was expecting/hoping for something like an event at the end of the item move, with the
QGraphicsItem
moved as an argument.It seems so simple: I just moved an item I set
ItemIsMovable
on, could you tell me which item just finished getting moved? Mine cannot be the only application which needs to act on that!You've commented on a similar topic two years ago :)
My idea was to use
QGraphicsItem::itemChange
, but turned out, it's not better than using::mouseReleaseEvent
,::mousePressEvent
and::mouseMoveEvent
. -
You've commented on a similar topic two years ago :)
My idea was to use
QGraphicsItem::itemChange
, but turned out, it's not better than using::mouseReleaseEvent
,::mousePressEvent
and::mouseMoveEvent
.@Pl45m4 said in Detect when QGraphicsItem dropped:
You've commented on a similar topic two years ago :)
Perfect! Lots of information there! No recollection, that's what senility does for you.
So unless there is a "move operation complete" signal (end of drag? drop? but not sure there is one) just recognise "mouse release" event and query pos() then. You could compare that against original position to see if moved, or set a flag for "moved" when get itemPositionHasChanged signal. Then emit your own signal for the end-of-move-with-position
I wrote that, it's what I was just thinking now. I am OK with subclassing, unlike the OP in that thread.
Now that I have seen https://doc.qt.io/qt-6/qgraphicsitem.html#GraphicsItemFlag-enum
QGraphicsItem::ItemIsMovable
This feature is provided as a convenience through the base implementation of QGraphicsItem's mouse event handlers.I'm much clearer :)
-
@Pl45m4
I have now had a chance to look at (I don't have Qt sources)ItemIsMovable
in Qt woboq sources. in https://codebrowser.dev/qt5/qtbase/src/widgets/graphicsview/qgraphicsitem.cpp.html. Much happier now that I can see how/when/what it does!As an aside, as per
QGraphicsItem::mouseMoveEvent()
at https://codebrowser.dev/qt5/qtbase/src/widgets/graphicsview/qgraphicsitem.cpp.html#7314, if you look at the amount of code handling particularly multiitem movement (which I will probably need) it seems to me to give the lie to people on the web who say "don't bother to useItemIsMovable
, simply switch if off and do it yourself in mouse events"... ! -
@Pl45m4
I have now had a chance to look at (I don't have Qt sources)ItemIsMovable
in Qt woboq sources. in https://codebrowser.dev/qt5/qtbase/src/widgets/graphicsview/qgraphicsitem.cpp.html. Much happier now that I can see how/when/what it does!As an aside, as per
QGraphicsItem::mouseMoveEvent()
at https://codebrowser.dev/qt5/qtbase/src/widgets/graphicsview/qgraphicsitem.cpp.html#7314, if you look at the amount of code handling particularly multiitem movement (which I will probably need) it seems to me to give the lie to people on the web who say "don't bother to useItemIsMovable
, simply switch if off and do it yourself in mouse events"... !@JonB said in Detect when QGraphicsItem dropped:
As an aside, as per QGraphicsItem::mouseMoveEvent() at https://codebrowser.dev/qt5/qtbase/src/widgets/graphicsview/qgraphicsitem.cpp.html#7314, if you look at the amount of code handling particularly multiitem movement (which I will probably need) it seems to me to give the lie to people on the web who say "don't bother to use ItemIsMovable, simply switch if off and do it yourself in mouse events"... !
I know, have also seen this.
The actual move (setPos
) call happens in L.7382. So almost 70 LoC to handle all transformations, selection groups, parent/childs that should move together, etc...Yeah, doing all this by yourself, while paying attention to every "trap" (e.g. not to detach the items from
QList selectedItems
, as noted in themouseMoveEvent
Impl.), might be tricky.
And is, for sure, more pain in the programmer's butt, than simply callingsetFlag(ItemIsMovable)
:) -
Well, today I discovered the "missing link" :) There is a
QGraphicsScene
method QGraphicsItem *QGraphicsScene::mouseGrabberItem() const:Returns the current mouse grabber item, or nullptr if no item is currently grabbing the mouse. The mouse grabber item is the item that receives all mouse events sent to the scene.
An item becomes a mouse grabber when it receives and accepts a mouse press event, and it stays the mouse grabber until either of the following events occur:
- If the item receives a mouse release event when there are no other buttons pressed, it loses the mouse grab.
Never came across this in all my searches of people trying to deal with end of
ItemIsMovable
drag. It's just what I needed. So I can handle this on the scene starting from:void MyGraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { QGraphicsItem *grabbedItem = mouseGrabberItem(); QGraphicsScene::mouseReleaseEvent(event); if (grabbedItem && !mouseGrabberItem()) emit itemMoved(grabbedItem); }
(With a bit more work we could of course discover and save the original
scenePos()
in amousePressEvent()
and compare inmouseReleaseEvent()
to see if different for actual move.) I haven't looked into selecting/moving multiple items yet. But this is all I ever wanted for now :)Thanks @Pl45m4 for your interest and help.
-
J JonB has marked this topic as solved on
-
J JonB referenced this topic on
-
Well, today I discovered the "missing link" :) There is a
QGraphicsScene
method QGraphicsItem *QGraphicsScene::mouseGrabberItem() const:Returns the current mouse grabber item, or nullptr if no item is currently grabbing the mouse. The mouse grabber item is the item that receives all mouse events sent to the scene.
An item becomes a mouse grabber when it receives and accepts a mouse press event, and it stays the mouse grabber until either of the following events occur:
- If the item receives a mouse release event when there are no other buttons pressed, it loses the mouse grab.
Never came across this in all my searches of people trying to deal with end of
ItemIsMovable
drag. It's just what I needed. So I can handle this on the scene starting from:void MyGraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { QGraphicsItem *grabbedItem = mouseGrabberItem(); QGraphicsScene::mouseReleaseEvent(event); if (grabbedItem && !mouseGrabberItem()) emit itemMoved(grabbedItem); }
(With a bit more work we could of course discover and save the original
scenePos()
in amousePressEvent()
and compare inmouseReleaseEvent()
to see if different for actual move.) I haven't looked into selecting/moving multiple items yet. But this is all I ever wanted for now :)Thanks @Pl45m4 for your interest and help.
@JonB said in Detect when QGraphicsItem dropped:
There is a QGraphicsScene method QGraphicsItem *QGraphicsScene::mouseGrabberItem() const:
Great find, but if I understand this correctly, things could become tricky because of:
If the item loses its mouse grab, the scene will
ignore all mouse events
until a new item grabs the mouse (i.e., until a new item receives a mouse press event).
From my understanding the scene is then unable to process any mouse event other than grabbing an item?!
Might work in your case, but any kind of user-defined selection or mouse interaction "stuff" would be omitted though?!
(don't know, not tested)
(looking atQRubberBand
or whatever you possibly have in your scene) -
@JonB said in Detect when QGraphicsItem dropped:
There is a QGraphicsScene method QGraphicsItem *QGraphicsScene::mouseGrabberItem() const:
Great find, but if I understand this correctly, things could become tricky because of:
If the item loses its mouse grab, the scene will
ignore all mouse events
until a new item grabs the mouse (i.e., until a new item receives a mouse press event).
From my understanding the scene is then unable to process any mouse event other than grabbing an item?!
Might work in your case, but any kind of user-defined selection or mouse interaction "stuff" would be omitted though?!
(don't know, not tested)
(looking atQRubberBand
or whatever you possibly have in your scene)@Pl45m4
I don't know but I don't think I care. It's not my responsibility. I am not doing anything other than looking atQGraphicsScene::mouseGrabberItem()
inmouseReleaseEvent()
. I am not doing anything to affect/alter how Qt infrastructure handles that, I am not in any way altering whateverItemIsMovable
does (or does not) do. To be clear, I find that if I am dragging/moving an item whenMyGraphicsScene::mouseReleaseEvent()
is hit then on entrymouseGrabberItem()
returns theQGraphicsItem
being pressed/moved, if any, and then after I call the baseQGraphicsScene::mouseReleaseEvent(event);
in the middlemouseGrabberItem()
then returnsnullptr
, i.e. it got "released". And my code concludes by saying "if there was a grabbed item on entry and now there is no grabbed item after processing the mouse release then emit a signal saying that item (may) have moved. Which a slot on the signal then decides to look at the item and do whatever (e.g. look where it is now and if necessary adjust some internal information about that).I don't see any flaw in that, I just want to be notified that an item has (possibly) moved (when it has finished being moved)?