QT5 拖拽事件


我們在編寫文本編輯器的時候,可能會希望其具有支持這種功能,將文件直接拖入文本編輯器打開。

使用方法

  • 1.包含頭文件
//拖拽事件
#include <QDragEnterEvent>
//放下事件
#include <QDropEvent>
  • 2.在類中加上如下聲明
    • 1)void dragEnterEvent(QDragEnterEvent *event);
    • 2)void dropEvent(QDropEvent *event);
class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    Ui::MainWindow *ui;

    //復寫”拖拽事件“函數
    void dragEnterEvent(QDragEnterEvent *event);

    //復寫”放下事件“函數
    void dropEvent(QDropEvent *event);
};
  • 3.在類的構造函數中設置接受drop事件
//拖拽事件, 也就是可以直接將要打開的文件, 拖入此窗口打開
this->setAcceptDrops(true);
  • 4.復寫“拖拽事件”函數
void MainWindow::dragEnterEvent(QDragEnterEvent *event)
{
    if(event->mimeData()->hasUrls())
    {
        event->acceptProposedAction();
    }
    else
    {
        event->ignore();
    }
}
  • 5.復寫“放下事件”函數
void MainWindow::dropEvent(QDropEvent *event)
{
    const QMimeData *mimeData = event->mimeData();

    if(!mimeData->hasUrls())
    {
        return;
    }

    QList<QUrl> urlList = mimeData->urls();

    //如果同時拖入了多個資源,只選擇一個
    QString fileName = urlList.at(0).toLocalFile();
    if(fileName.isEmpty())
    {
        return;
    }

    //打開拖入的文件
    QFile file(fileName);
    if(!file.open(QIODevice::ReadOnly))
    {
        QMessageBox::information(this, "錯誤", file.errorString(), QMessageBox::Ok);
        return;
    }

    //將文件內容放入文本框
    QByteArray ba;
    ba = file.readAll();
    ui->textEdit->setText(QString(ba));
}
  • 6.效果
    • 1)拖入mainWindow,也就是我的主窗口


      這表示是成功的,注意這里拖入的是mainWindow
    • 2)拖入textEdit和mainWindow的重疊區域


      這里顯然是失敗的,為什么會這樣?
  • 7.分析

查看官方幫助文檔,關於setAcceptDrops(bool on)有如下說明:
acceptDrops : bool
This property holds whether drop events are enabled for this widget
Setting this property to true announces to the system that this widget may be able to accept drop events.
If the widget is the desktop (windowType() == Qt::Desktop), this may fail if another application is using the desktop; you can call acceptDrops() to test if this occurs.
Warning: Do not modify this property in a drag and drop event handler.
By default, this property is false.
Access functions:
bool acceptDrops() const
void setAcceptDrops(bool on)

關鍵的地方是:設置這個屬性有可能會失敗
我的窗口里面有一個textEdit,textEdit也能接受drop事件,懷疑可能是這個原因

  • 8.解決
    我在構造函數將textEdit接受drop事件禁用掉
//禁用textEdit的拖拽事件
ui->textEdit->setAcceptDrops(false);


至此,能愉快的拖放了。

  • 9.總結
1.這里只是打開了mainWindow接受drop事件,而沒有打開textEdit接受drop事件。
2.就drop事件來說,默認是關閉的。
3.為什么textEdit的drop事件也被開啟了,導致mainWindow的drop事件沒觸發。
4.懷疑“事件過濾器”在mainWindow/widget等窗口控件上,設置接受某個事件后,窗口上的子控件也能接受該事件。
5.如果想只是觸發mainWindow的事件,而子部件不需要,則需要將子部件該事件禁用掉。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM