At first, I wanted to use qgraphicsview in combination with qgraphicsscene and qgraphicsitem to create an editor for drawing various graphics. I did not expect any further twists and turns when I wanted to use drag and drop to implement shortcuts.
Setacceptdrops (true) has been set in qgraphicsvews );
During running, it is found that when the drag icon is placed on qgraphicsvews, the drag-and-drop shape is still displayed, but dragenterevent can be triggered. However, the dropevent cannot be triggered.
After a drag-and-drop event is received, the view forwards the event to the associated scenario for processing. However, the dropevent is not overwritten in the scenario.
Today, I actually tracked the following:
1. Drag it to qgraphicsview to trigger its dragenterevent event:
void QGraphicsView::dragEnterEvent(QDragEnterEvent *event){#ifndef QT_NO_DRAGANDDROP Q_D(QGraphicsView); if (!d->scene || !d->sceneInteractionAllowed) return; // Disable replaying of mouse move events. d->useLastMouseEvent = false; // Generate a scene event. QGraphicsSceneDragDropEvent sceneEvent(QEvent::GraphicsSceneDragEnter); d->populateSceneDragDropEvent(&sceneEvent, event); // Store it for later use. d->storeDragDropEvent(&sceneEvent); // Send it to the scene. QApplication::sendEvent(d->scene, &sceneEvent); // Accept the originating event if the scene accepted the scene event. if (sceneEvent.isAccepted()) { event->setAccepted(true); event->setDropAction(sceneEvent.dropAction()); }#else Q_UNUSED(event)#endif}
The above functions are mainly used to check whether there is a scenario, and then forward the event to the scenario for processing. Of course, they are transferred to the scenario for processing when conditions permit.
2. Scenario dragenterevent
void QGraphicsScene::dragEnterEvent(QGraphicsSceneDragDropEvent *event){ Q_D(QGraphicsScene); d->dragDropItem = 0; d->lastDropAction = Qt::IgnoreAction; event->accept();}
The dragenterevent in the scenario is actually very easy to receive drag events.
3. This is the focus of the dragmoveevent event in the scenario.
void QGraphicsScene::dragMoveEvent(QGraphicsSceneDragDropEvent *event){ Q_D(QGraphicsScene); event->ignore(); if (!d->mouseGrabberItems.isEmpty()) { // Mouse grabbers that start drag events lose the mouse grab. d->clearMouseGrabber(); d->mouseGrabberButtonDownPos.clear(); d->mouseGrabberButtonDownScenePos.clear(); d->mouseGrabberButtonDownScreenPos.clear(); } bool eventDelivered = false; // Find the topmost enabled items under the cursor. They are all // candidates for accepting drag & drop events. foreach (QGraphicsItem *item, d->itemsAtPosition(event->screenPos(), event->scenePos(), event->widget())) { if (!item->isEnabled() || !item->acceptDrops()) continue; if (item != d->dragDropItem) { // Enter the new drag drop item. If it accepts the event, we send // the leave to the parent item. QGraphicsSceneDragDropEvent dragEnter(QEvent::GraphicsSceneDragEnter); d->cloneDragDropEvent(&dragEnter, event); dragEnter.setDropAction(event->proposedAction()); d->sendDragDropEvent(item, &dragEnter); event->setAccepted(dragEnter.isAccepted()); event->setDropAction(dragEnter.dropAction()); if (!event->isAccepted()) { // Propagate to the item under continue; } d->lastDropAction = event->dropAction(); if (d->dragDropItem) { // Leave the last drag drop item. A perfect implementation // would set the position of this event to the point where // this event and the last event intersect with the item's // shape, but that's not easy to do. QGraphicsSceneDragDropEvent dragLeave(QEvent::GraphicsSceneDragLeave); d->cloneDragDropEvent(&dragLeave, event); d->sendDragDropEvent(d->dragDropItem, &dragLeave); } // We've got a new drag & drop item d->dragDropItem = item; } // Send the move event. event->setDropAction(d->lastDropAction); event->accept(); d->sendDragDropEvent(item, event); if (event->isAccepted()) d->lastDropAction = event->dropAction(); eventDelivered = true; break; } if (!eventDelivered) { if (d->dragDropItem) { // Leave the last drag drop item QGraphicsSceneDragDropEvent dragLeave(QEvent::GraphicsSceneDragLeave); d->cloneDragDropEvent(&dragLeave, event); d->sendDragDropEvent(d->dragDropItem, &dragLeave); d->dragDropItem = 0; } // Propagate event->setDropAction(Qt::IgnoreAction); }}
Obviously, this event is ignored during the Drag and Drop Process, and the main response is the possible item drag events in the scenario.
If you see this, you will have an answer to the question. The subclass scenario class is rewritten to dragmoveevent.
void QGraphicsScene::dragMoveEvent(QGraphicsSceneDragDropEvent *event){ event->accept();}
Rewrite the dropevent and perform the drag and drop operations.