Qt學習之路28--拖放事件

什麼是拖放事件?

將一個文件往應用程序窗口裏拖放時,操作系統能感知這個動作,併發送系統消息到應用程序後會產生一個拖放事件。
拖放事件分爲兩部分,將文件拖到窗口內部和鬆開鼠標。

怎麼處理拖放事件?

  • 所有的QWidget對象都能處理拖放事件
  • 通過兩個函數實現事件處理(分別對應拖和放):
    -void dragEnterEvent(QDragEnterEvent* event);這個事件處理程序在拖動過程中被調用,當鼠標拖動文件進入當前QWidget對象中時,拖拽事件通過參數event進行傳遞,如果拖拽事件被忽略後,當前QWidget對象就不會收到任何相關消息。
    -void dropEvent(QDropEvent* event) ;當拖拽被放下時將會產生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對象都能處理拖拽事件。
  • 通過三部曲處理自定義拖拽事件。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章