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 源码超详细解读】

发布了194 篇原创文章 · 获赞 443 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/weixin_42837024/article/details/105557761
今日推荐