前言:
看幾天看了 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個函數 怎麼把數據拖拽過去的
首先 拖拽由兩部分組成
- 按壓鼠標
- 移動鼠標
按壓鼠標時 我們獲取鼠標在整個屏幕的位置
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 源碼超詳細解讀】