Qt 實現拖放內容 drag - drop 【簡單明瞭】

前言:

看幾天看了 Qt 實現跨‘窗口’,‘程序’ 拖拽 文件,信息,圖片之類
感覺看完他們寫的文章 ,還是不太明白 自己看了看 試了試
寫這篇文章鞏固一下

本文說的比較詳細簡單

我下面錄製的 gif 因爲拖拽時 的圖標不會被錄製進去 觀看會受到極大的影響

在這裏插入圖片描述

下面是我用手機照的照片

移動過程中 …
在這裏插入圖片描述
在這裏插入圖片描述

我們仔細的看這個過程

1.當我們鼠標 點擊 send widget 時候 會觸發 mousePressEvent
2. 當我們按壓鼠標 移動的過程中 會觸發 mouseMoveEvent
3. 當我們拖拽鼠標進入窗口 recv widget 會觸發 dragEnterEvent
4. 當我們鬆開鼠標 會觸發 dropEvent

sendWidget.h


#include <QMainWindow>

class QLineEdit;
class recvWidget;



class MainWindow : public QMainWindow
{
    Q_OBJECT

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


protected:
    void mousePressEvent(QMouseEvent *event) override;
    void mouseMoveEvent(QMouseEvent *event) override;

private:
    QPointF m_pressPoint;
    QLineEdit *m_lineEdit;
    bool m_isMoving;

    recvWidget *m_recvWidget;
};

sendWidget.cpp

#include "recvwidget.h"

#include <QMouseEvent>
#include <QLineEdit>
#include <QApplication>
#include <QDrag>
#include <QMimeData>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent)
{
    this->resize(300,200);
    this->setWindowTitle("send widget");

    m_lineEdit = new QLineEdit(this);
    m_recvWidget = new recvWidget();
    m_recvWidget->show();

}

MainWindow::~MainWindow()
{
    delete m_lineEdit;
}

void MainWindow::mousePressEvent(QMouseEvent *event)
{
    qDebug()<<"[mainWindow]:mousePress";
    m_pressPoint = event->screenPos();
    m_isMoving = false;
}

void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
    if(QLineF(event->screenPos(),m_pressPoint).length() < QApplication::startDragDistance() || m_isMoving)
        return;
    qDebug()<<"[mainWindow]:mouseMove";

    m_isMoving = true;

    QDrag *drag = new QDrag(this);
    QMimeData *mimeData = new QMimeData();

    QPixmap pixmap("C://Users//Administrator//Desktop//icon.jpg");
    drag->setPixmap(pixmap);
    drag->setHotSpot(QPoint(20,30));

    drag->setMimeData(mimeData);

    QByteArray byteArray(m_lineEdit->text().toUtf8());

    mimeData->setData("text",byteArray);

    drag->exec();

}

咱們 sendWidget 就說1個函數 怎麼把數據拖拽過去的

在這裏插入圖片描述

首先 拖拽由兩部分組成

  1. 按壓鼠標
  2. 移動鼠標

按壓鼠標時 我們獲取鼠標在整個屏幕的位置

if(QLineF(event->screenPos(),m_pressPoint).length() < QApplication::startDragDistance() || m_isMoving)
    return;

開始移動時候 我們判斷一下 我們按壓的位置 和 現在移動到的位置 他們之間的距離
是不是大於 dragDistance 的距離 默認是10像素

在這裏插入圖片描述

距離達不到就不算拖拽

當達到拖拽條件以後

在這裏插入圖片描述

有的可能不懂 QMimeData 了

在這裏插入圖片描述

譯文:
QMimeData類爲記錄其MIME類型信息的數據提供了一個容器。
QMimeData用於描述可以存儲在剪貼板中的信息,並通過拖放機制進行傳輸。QMimeData對象將它們持有的數據與相應的MIME類型相關聯,以確保信息可以在應用程序之間安全地傳輸,並在同一個應用程序中進行復制。
QMimeData對象通常使用新的並提供給QDrag或QClipboard對象來創建。這是爲了使Qt能夠管理它們所使用的內存。

單個QMimeData對象可以同時使用幾種不同的格式存儲相同的數據。函數的作用是:按優先順序返回可用格式的列表。data()函數返回與MIME類型關聯的原始數據,而setData()允許您設置MIME類型的數據。
對於最常見的MIME類型,QMimeData提供了方便的函數來訪問數據:

通俗講 就是把你想發的數據 必須由 QMimeData 包裝一下 才能被另一個收到

在這裏插入圖片描述

我設置了一個 拖拽時的 鼠標的icon 就是他在這裏插入圖片描述

setHotSpot 就是設置 讓不接收拖拽時的 叉號 的位置

在這裏插入圖片描述
下面就是把我們的 lineEdit 的數據 用 QbyteArray 存儲一下 放到 QMimeData

前面的 “text” 非常重要 是mimetype
就相當於 是密碼
接收數據的一方想要 拆開 QMimeData 的數據 必須要 輸對 mimetype

mimeData->setData("text",byteArray);

ok 這樣一個發送方的 拖拽數據就準備好了

下面看接收方的

recvWidget.h

#include <QWidget>
class QLabel;
class recvWidget : public QWidget
{
    Q_OBJECT
public:
    explicit recvWidget(QWidget *parent = nullptr);
protected:
    void dropEvent(QDropEvent *event) override;
    void dragEnterEvent(QDragEnterEvent *event)override;

private:
    QLabel* m_label;
};
#include "recvwidget.h"
#include <QDropEvent>
#include <QMimeData>
#include <QDebug>
#include <QLabel>


recvWidget::recvWidget(QWidget *parent) : QWidget(parent)
{
    this->resize(300,200);
    this->setWindowTitle("recv widget");

    m_label = new QLabel(this);
    m_label->setText("等待接收拖拽數據......");

    QFont font;
    font.setPixelSize(16);
    m_label->setFont(font);

    this->setAcceptDrops(true);
}

void recvWidget::dragEnterEvent(QDragEnterEvent *event)
{
    if(event->mimeData()->hasFormat("text"))
    {
        event->accept();
        qDebug()<<"[recvWidget]: dragEnterEvent accept";
    }
    else
        event->ignore();
}

void recvWidget::dropEvent(QDropEvent *event)
{
    qDebug()<<"[recvWidget]:dropEvent drop";

    if(event->mimeData()->hasFormat("text"))
    {
        QByteArray byteArray = event->mimeData()->data("text");
        m_label->setText("recv:"+QString(byteArray));

        event->setDropAction(Qt::MoveAction);
        event->accept();
    }
    else
        event->ignore();

}

首先 注意 如果要使窗口 能接收拖拽事件 必須開啓接收drop

    this->setAcceptDrops(true);

還是隻看 這倆函數

在這裏插入圖片描述

dragEnterEvent 事件是 鼠標進入到本窗口

只要你按着鼠標移動到 窗口裏面 不用鬆手
就會進入 dragEnterEvent 事件

前提是你要 accept

在這裏插入圖片描述

event->mimeData()->hasFormat("text")

就是判斷這個 拖拽來的東西 是不是我們想要的

就相當於快遞員給你送快遞 你看到快遞 看上面單號是不是你的就行 不需要拆開看裏面的東西

在這裏插入圖片描述
dropEvent 是松鼠標以後 進入的事件
把數據拆開 顯示就ok 了

這是個很基礎 簡單 便於我們理解

後面咱們來看一下 Qt 官方demo 拼圖的 源碼
Qt 實現拼圖【官方demo 源碼超詳細解讀】

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章