qt中的拖拽及其提示

來源:互聯網
上載者:User

關於qt中的拖放操作,首先可以看這篇官方文檔:http://doc.qt.io/qt-5.5/dnd.html

一、QDrag

首先是建立QDrag,可以在mousePressEvent或者mouseMoveEvent中建立。

void DragDropWidget::mousePressEvent(QMouseEvent *event){if (event->button() == Qt::LeftButton){QDrag *drag = new QDrag(this);QMimeData *data = new QMimeData;drag->setMimeData(data);drag->exec(Qt::MoveAction);}}
或者
void DragDropWidget::mousePressEvent(QMouseEvent *event){if (event->buttons() & Qt::LeftButton){startPos = event->pos();}}void DragDropWidget::mouseMoveEvent(QMouseEvent *event){if (event->buttons() & Qt::LeftButton){if ((event->pos() - startPos).manhattanLength() < QApplication::startDragDistance()){QDrag *drag = new QDrag(this);QMimeData *data = new QMimeData;drag->setMimeData(data);drag->exec(Qt::LinkAction);}}}
QDrag在exec前,一定要設定QMimeData,否則會彈出警告“QDrag: No mimedata set before starting the drag”。並且不會開始拖拽操作。

QMimeData在拖拽中非常有用,可以用來儲存拖拽操作附帶的資訊,比如字串、檔案或者圖片,同時也可以用來驗證其所儲存的資訊格式,並以此來判斷是否可接收。未來再補充QMimeData的用法。

另外要注意,在windows下,QDrag::exec()是個同步操作,要在exec()返回後,才會繼續執行下面的代碼。

二、drag相關事件

首先,當需要一個控制項接收drag和drop,就要先調用控制項的方法:setAcceptDrops(true)。

qt中一共有三個drag相關事件,dragEnterEvent、dragMoveEvent、dragLeaveEvent。這三個事件觸發條件類似滑鼠移入,滑鼠移動,滑鼠移出。當滑鼠拖拽進入控制項觸發dragEnterEvent,在控制項內拖拽移動觸發dragMoveEvent,滑鼠拖拽離開控制項觸發dragLeaveEvent。

dragEnterEvent事件有一個參數,參數類型是QDragEnterEvent,繼承自QDragMoveEvent。

dragMoveEvent事件有一個參數,參數類型是QDragMoveEvent。

dragLeaveEvent事件有一個參數,參數類型是QDragLeaveEvent,繼承自QEvent,無特別用法。

當滑鼠拖拽進入控制項時,會觸發dragEnterEvent,如果不做處理,後續將不會接收到dragMoveEvent事件和dragLeaveEvent事件。在dragEnterEvent事件中,如果調用了QDragMoveEvent::accept()函數,後續將可以收到dragMoveEvent事件和dragLeaveEvent事件。而如果調用QDragMoveEvent::ignore()函數,效果相當於不處理,不會接收後續事件。

void DragDropWidget::dragEnterEvent(QDragEnterEvent *event){if (event->source() == this)event->ignore();elseevent->accept();}
發起drag的控制項自身也是可以接受到來自自身的drag的相關事件的,這個要注意,處理不好容易出bug。

三、dropEvent

當drag為accept狀態,然後釋放滑鼠,就會產生dropEvent。我們可以在這個事件裡處理本次拖拽附帶的Mime資訊。


四、提示

在我的一個項目中,需要通過拖拽操作串連兩個控制項,然後在兩個控制項之間畫連接線。這裡有兩種控制項,畫布控制項CanvasWidget,和節點控制項NodeWidget。NodeWidget在CanvasWidget上,連接線也是在CanvasWidget上繪製。我們可以在NodeWidget的dropEvent事件裡給CanvasWidget發送串連訊號,告訴CanvasWidget兩個NodeWidget已經相連了。

void NodeWidget::dropEvent(QDropEvent *event){auto src = event->source();event->setDropAction(Qt::LinkAction);event->accept();emit linked(src, this);}

然後我又想在拖拽的過程中就看到一條動態連接線,這時候就要用到CanvasWidget的drag相關事件。在CanvasWidget的dragMoveEvent事件中這樣處理:

void CanvasWidget::dragMoveEvent(QDragMoveEvent *event){m_lineDraging.end = event->pos();update();}

m_lineDraging就是用來繪製的動態連接器。設定完連接線的端點,然後再update()一下,就可以顯示了。當然這隻是一個簡單方案,還沒有驗證過在繪製量較大時,在move事件中update會不會很卡。

下面是效果圖

Qt Drag and Drop思維導圖



參考資料: http://doc.qt.io/qt-5.5/dnd.html http://blog.csdn.net/pcsuite/article/details/6147191

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.