前言:
看几天看了 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 源码超详细解读】