Qt學習之路28--拖放事件
阿新 • • 發佈:2019-02-17
什麼是拖放事件?
將一個檔案往應用程式窗口裡拖放時,作業系統能感知這個動作,併發送系統訊息到應用程式後會產生一個拖放事件。
拖放事件分為兩部分,將檔案拖到視窗內部和鬆開滑鼠。
怎麼處理拖放事件?
- 所有的QWidget物件都能處理拖放事件
- 通過兩個函式實現事件處理(分別對應拖和放):
-void dragEnterEvent(QDragEnterEvent* event);這個事件處理程式在拖動過程中被呼叫,當滑鼠拖動檔案進入當前QWidget物件中時,拖拽事件通過引數event進行傳遞,如果拖拽事件被忽略後,當前QWidget物件就不會收到任何相關訊息。
-void dropEvent(QDropEvent* event) ;
所以在拖放事件的處理上需要對拖和放兩個動作進行處理。
拖放事件中的QMimeData
- QMimeData是Qt中的多媒體資料類
- 拖放事件通過QMimeData物件傳遞資料
- QMimeData支援多種不同型別的多媒體資料,包括文字、html資料、合法路徑、圖片、顏色等。
- 操作QMimeData資料物件的常用函式:
包含測試MIME資料的型別、獲取MIME資料和設定MIME資料。
自定義拖放事件步驟
- 首先需要對接收拖放事件的物件呼叫setAcceptDrops(bool on);該屬性作用為設定QWidget物件是否可以接收QDropEvent事件,預設為不接收此事件。注意:不要在拖放事件處理函式裡面修改該屬性。
- 重寫dragEnterEvent(QDragEnterEvent* event)事件處理函式,並判斷MIME資料型別
-期望資料:呼叫event->acceptProposedAction()接收該資料
-其他資料:呼叫event->ignore()忽略該資料 - 重寫dropEvent(QDropEvent* event)事件處理函式,並判斷MIME資料型別
-期望資料:從物件中獲取MIME資料並進行處理
-其他資料:呼叫e->ignore()忽略該資料
自定義拖放事件試驗
自定義一個Widget類,公有繼承自QWidget。
其標頭檔案如下:
class Widget : public QWidget
{
Q_OBJECT
protected:
void dragEnterEvent(QDragEnterEvent* e);//重新實現兩個事件處理函式
void dropEvent(QDropEvent* e);
public:
Widget(QWidget *parent = 0);
~Widget();
};
原始檔如下:
根據實際使用情況新增相應的標頭檔案。
Widget::Widget(QWidget *parent) : QWidget(parent)
{
setAcceptDrops(true);//set this widget able to accept drop events
}
void Widget::dragEnterEvent(QDragEnterEvent* e)//拖
{
if(e->mimeData()->hasUrls())//判斷資料型別
{
e->acceptProposedAction();//接收該資料型別拖拽事件
}
else
{
e->ignore();//忽略
}
}
void Widget::dropEvent(QDropEvent* e)//放
{
if(e->mimeData()->hasUrls())//處理期望資料型別
{
QList<QUrl> list = e->mimeData()->urls();//獲取資料並儲存到連結串列中
for(int i = 0; i < list.count(); i++)
{
qDebug() << list[i].toLocalFile();
}
}
else
{
e->ignore();
}
}
通過將選中的檔案條目拖拽到Widget視窗並鬆開滑鼠後就會觸發拖放事件,根據程式碼的處理方式就是將所獲得的路徑通過qDebug()打印出來。
擴充套件:文字編輯器中的拖放事件
可以通過重寫拖拽事件處理函式增加拖拽檔案到主視窗後開啟檔案的功能。
解決方案:
- 呼叫主視窗物件的setAcceptDrops()函式
- 重寫dragEnterEvent(QDragEnterEvent* event)函式並判斷MIME資料型別
- 重寫dropEvent(QDropEvent* event)函式判斷MIME資料型別後開啟檔案
- 具體實現和之前試驗程式碼框架基本一樣,不同的只是dropEvent函式裡的處理形式不同。
void MainWindow::dropEvent(QDropEvent* e)
{
if( e->mimeData()->hasUrls() )
{
QList<QUrl> list = e->mimeData()->urls();
QString path = list[0].toLocalFile();
QFileInfo fi(path);
if( fi.isFile() )
{
preEditorChange();//儲存編輯器中未儲存的內容
if( !m_isTextChanged )//檔案未修改
{
openFileToEditor(path);//開啟path對應的檔案
}
}
else
{
showErrorMessage("Cannot open a folder!");
}
}
else
{
e->ignore();
}
}
小結
- 拖拽事件分為兩部分:拖和放。
- 所有的QWidget物件都能處理拖拽事件。
- 通過三部曲處理自定義拖拽事件。