QMimeData
- 用于描述可储存在剪贴板中的信息,并支持通过拖放机制传输
- 将它们所持有的数据与相应的 MIME 类型相关联,以确保信息可以在应用程序内,应用程序之间安全传输
QByteArray
- 字节数组容器,相当于方便版的 const char*,或者8位的 QString
- 可以用于存储原始的二进制数据,也可以在内存紧张的情况下节省内存,例如嵌入式开发
- QMimeData 中自定义数据类型通常为 QByteArray
QPixmap
- 与 QImage 类似,但是不如 QImage 操作灵活
- QLabel 中的图片即使通过 QPixmap 储存的
QDrag
- 可以设置 QMimeData,QPixmap 和 拖动位置等
- 需要设置 QWidget::setAcceptDrops(true) 才能接受 dropEvent
拖拽的基本流程
- mousePressEvent 中定义 QDrag 并开启拖拽(QDrag::exec()),同时还要完成拖拽后的后续处理
- dragEnterEvent 中处理拖拽过程中的逻辑
- dropEvent 中重建拖拽的对象,并确定 QDrag::exec() 的返回值
代码示例
#include "dragform.h"
#include "ui_dragform.h"
DragForm::DragForm(QWidget *parent) :
QFrame(parent),
ui(new Ui::DragForm)
{
ui->setupUi(this);
this->setAcceptDrops(true);
}
DragForm::~DragForm()
{
delete ui;
}
void DragForm::mousePressEvent(QMouseEvent *event)
{
QWidget* child = this->childAt(event->position().toPoint());
QLabel* label = qobject_cast<QLabel*>(child);
if (label == nullptr)
{
return;
}
QPixmap pixmap = label->pixmap();
QPoint relativePosition = event->position().toPoint() - child->pos();
QByteArray itemData;
QDataStream dataStream(&itemData, QIODevice::WriteOnly);
dataStream << pixmap << relativePosition;
QMimeData* mimeData = new QMimeData();
mimeData->setData("Application/DragIcon", itemData);
QDrag* drag = new QDrag(this);
drag->setMimeData(mimeData);
drag->setPixmap(pixmap);
drag->setHotSpot(relativePosition);
QPixmap maskedPixmap = pixmap;
QPainter painter;
painter.begin(&maskedPixmap);
painter.fillRect(child->rect(), QColor(127, 127, 127, 127));
painter.end();
label->setPixmap(maskedPixmap);
if (drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction) == Qt::MoveAction)
{
child->close();
}
else
{
label->setPixmap(pixmap);
}
}
void DragForm::dragEnterEvent(QDragEnterEvent *event)
{
if (event->mimeData()->hasFormat("Application/DragIcon"))
{
if (event->source() == this)
{
event->setDropAction(Qt::MoveAction);
event->accept();
}
else
{
event->acceptProposedAction();
}
}
else
{
event->ignore();
}
}
void DragForm::dropEvent(QDropEvent *event)
{
if (event->mimeData()->hasFormat("Application/DragIcon"))
{
QPixmap pixmap;
QPoint relativePosition;
QByteArray itemData = event->mimeData()->data("Application/DragIcon");
QDataStream dataStream(&itemData, QIODevice::ReadOnly);
dataStream >> pixmap >> relativePosition;
qDebug() << relativePosition;
QLabel* label = new QLabel(this);
label->resize(64, 64);
label->setPixmap(pixmap);
label->move(event->position().toPoint() - relativePosition);
label->show();
if (event->source() == this)
{
event->setDropAction(Qt::MoveAction);
event->accept();
}
else
{
event->acceptProposedAction();
}
}
else
{
event->ignore();
}
}