QGraphicsView 中實現拖拽

來源:互聯網
上載者:User

開始想使用QGraphicsView結合QGraphicsScene和QGraphicsItem,做個繪製各種圖形的編輯器,想使用拖拽實現捷徑,沒想到還有點波折。

已在QGraphicsVews中設定了setAcceptDrops(true);

在運行時發現:當把拖拽的表徵圖放到QGraphicsVews上時,顯示的還是不可拖拽的形狀,但dragEnterEvent可以觸發。但後面的dropEvent就不能觸發了。

上網一查,視圖接收到拖拽事件後會轉交給關聯的情境處理,但是在情境中重寫dropevent還是沒有撲捉到事件。

今天實際跟蹤了一下:

1、拖拽首先進入QGraphicsView觸發其dragEnterEvent事件:

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}

上述函數主要是查看有沒有情境,然後將事件轉交給情境處理,當然是在條件允許的情況下轉交給情境處理。

2、情境的dragEnterEvent

void QGraphicsScene::dragEnterEvent(QGraphicsSceneDragDropEvent *event){    Q_D(QGraphicsScene);    d->dragDropItem = 0;    d->lastDropAction = Qt::IgnoreAction;    event->accept();}

情境的dragenterEvent其實很簡單就是接收拖拽事件

3、情境的dragMoveEvent事件,重點就在於此

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);    }}

很顯然,在拖拽移動過程中忽略了該事件,主要響應的是情境內可能存在的item拖拽事件

看到這,問題就有答案了,subclass情境類,重寫dragMoveEvent

void QGraphicsScene::dragMoveEvent(QGraphicsSceneDragDropEvent *event){    event->accept();}

最後重寫dropEvent,做最後拖拽處理就是了。


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.