Detect when QGraphicsItem dropped
-
wrote on 30 May 2024, 14:45 last edited by
Per the title, all I need to know is "when QGraphicsItem dropped"?
I have a
QGraphicsScene
,QGraphicsView
and someQGraphicsItem
s on the scene/view. My items haveQGraphicsItem::ItemIsMovable
flag. I can drag them around the scene/view, and they stay where I drag them to/drop/release mouse, whichever you wish.This is all perfect. The only think I need to know is when they are dropped, so that I can run some code. All the examples involve
QDrag
objects/operations, overriding mouse events, accepting actions, reading mime types, ... Do I really need any of these when everything is working perfectly as-is with none of them but I just need notification when the dragged graphics item is released somewhere at the end of the drag/drop? -
wrote on 31 May 2024, 13:59 last edited by JonB
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.
-
Per the title, all I need to know is "when QGraphicsItem dropped"?
I have a
QGraphicsScene
,QGraphicsView
and someQGraphicsItem
s on the scene/view. My items haveQGraphicsItem::ItemIsMovable
flag. I can drag them around the scene/view, and they stay where I drag them to/drop/release mouse, whichever you wish.This is all perfect. The only think I need to know is when they are dropped, so that I can run some code. All the examples involve
QDrag
objects/operations, overriding mouse events, accepting actions, reading mime types, ... Do I really need any of these when everything is working perfectly as-is with none of them but I just need notification when the dragged graphics item is released somewhere at the end of the drag/drop?wrote on 30 May 2024, 15:02 last edited by Pl45m4So you want to know when the movable item was released (move operation has stopped)?!
I also think you don't needQDrop
for this.What about a mix of
QGraphicsItem::mousePressEvent
,QGraphicsItem::mouseMoveEvent
andQGraphicsItem::mouseReleaseEvent
?
Have you tried using these 3 in combination?
When the moving has stopped and the mouse was released, the item was "dropped", right?! -
So you want to know when the movable item was released (move operation has stopped)?!
I also think you don't needQDrop
for this.What about a mix of
QGraphicsItem::mousePressEvent
,QGraphicsItem::mouseMoveEvent
andQGraphicsItem::mouseReleaseEvent
?
Have you tried using these 3 in combination?
When the moving has stopped and the mouse was released, the item was "dropped", right?!wrote on 30 May 2024, 17:27 last edited by JonB@Pl45m4
If I have to. But why do I have to do all this? The move of theQGraphicsItem
by dragging is already working 100%. I simply want to know where it ends up/that the drag has finished. Which Qt certainly knows. And there will be othermouseReleaseEvent
s (e.g. clicking) which I will have to distinguish from "end of drag". This really ought be easy, knowing when a item has been dragged and it's done dragging is a common enough thing to want to write code on. -
@Pl45m4
If I have to. But why do I have to do all this? The move of theQGraphicsItem
by dragging is already working 100%. I simply want to know where it ends up/that the drag has finished. Which Qt certainly knows. And there will be othermouseReleaseEvent
s (e.g. clicking) which I will have to distinguish from "end of drag". This really ought be easy, knowing when a item has been dragged and it's done dragging is a common enough thing to want to write code on.wrote on 30 May 2024, 17:32 last edited by -
wrote on 30 May 2024, 19:03 last edited by JonB
@JoeCFD
I don't think it would be that gfx item event.QGraphicsScene::dropEvent(QGraphicsSceneDragDropEvent *event) seems more like it to me. But from the
QGraphicsSceneDragDropEvent
I don't see how I get theQGraphicsItem
item which was dropped/moved (if you can, show me how)....With the
QGraphicsItem::ItemIsMovable
flag set, when it allows you to drag aQGraphicsItem
around, is that "drag and drop"?If you move the pixmap item, then there is no drag&drop involved at all.
Thanks, I got confused, I needed to use mouseReleaseEvent
-
@JoeCFD
I don't think it would be that gfx item event.QGraphicsScene::dropEvent(QGraphicsSceneDragDropEvent *event) seems more like it to me. But from the
QGraphicsSceneDragDropEvent
I don't see how I get theQGraphicsItem
item which was dropped/moved (if you can, show me how)....With the
QGraphicsItem::ItemIsMovable
flag set, when it allows you to drag aQGraphicsItem
around, is that "drag and drop"?If you move the pixmap item, then there is no drag&drop involved at all.
Thanks, I got confused, I needed to use mouseReleaseEvent
wrote on 30 May 2024, 19:06 last edited by@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). -
@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.
-
wrote on 30 May 2024, 19:24 last edited by JonB
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!wrote on 30 May 2024, 20:11 last edited byYou'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
.wrote on 30 May 2024, 20:21 last edited by JonB@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 :)
-
wrote on 31 May 2024, 10:30 last edited by JonB
@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"... !wrote on 31 May 2024, 12:51 last edited by Pl45m4@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)
:) -
wrote on 31 May 2024, 13:59 last edited by JonB
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.
-
-
-
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.
wrote on 31 May 2024, 15:07 last edited by Pl45m4@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)wrote on 31 May 2024, 15:17 last edited by JonB@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)?
1/16