/.h文件
#ifndef PROJECTLISTWIDGET_H
#define PROJECTLISTWIDGET_H
#include<QPoint>
#include<QListWidget>
#include<QMouseEvent>
#include<QApplication>
#include<QMimeData>
#include<QDrag>
class ProjectListWidget : public QListWidget
{
Q_OBJECT

public:
ProjectListWidget(QWidget *parent = 0);

protected:
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void dragEnterEvent(QDragEnterEvent *event);
void dragMoveEvent(QDragMoveEvent *event);
void dropEvent(QDropEvent *event);

private:
void performDrag();

QPoint startPos;
};

#endif // PROJECTLISTWIDGET_H
//.cpp文件
#include "projectlistwidget.h"

ProjectListWidget::ProjectListWidget(QWidget *parent)
: QListWidget(parent)
{
setAcceptDrops(true);//设置组件接受拖放事件
}

void ProjectListWidget::mousePressEvent(QMouseEvent *event)
{//鼠标按下事件,
if (event->button() == Qt::LeftButton)
startPos = event->pos();//如果按下左键,记录当前的坐标
//这里调用系统自带的处理函数,以便实现通用的功能
QListWidget::mousePressEvent(event);
}

void ProjectListWidget::mouseMoveEvent(QMouseEvent *event)
{//这里判断是否一直按着左键
if (event->buttons() & Qt::LeftButton) {
//计算一个曼哈顿长度
int distance = (event->pos() - startPos).manhattanLength();
//这里做一个判断大于=开始拖动的距离执行performDrag处理
if (distance >= QApplication::startDragDistance())
performDrag();
}
QListWidget::mouseMoveEvent(event);//最后调用系统自带的函数处理事件
}

void ProjectListWidget::performDrag()
{
QListWidgetItem *item = currentItem();
//用于与QListWidget项视图类项目,currentItem返回当前项
if (item) {
//提供了用于记录的MIME类型信息数据容器
QMimeData *mimeData = new QMimeData;
mimeData->setText(item->text());

QDrag *drag = new QDrag(this);//该QDrag类提供了通过拖放数据传输MIME支持
drag->setMimeData(mimeData);//设置数据
drag->setPixmap(QPixmap("qrc:/images/test.png"));//设置图片
if (drag->exec(Qt::MoveAction) == Qt::MoveAction)
{delete item;}
//QDrag::exec() 会阻塞拖动的操作,直到用户完成操作或者取消操作
}
}

void ProjectListWidget::dragEnterEvent(QDragEnterEvent *event)
{
ProjectListWidget *source =
qobject_cast<ProjectListWidget *>(event->source());
// event->source()获取对象
if (source && source != this) {//来自同一应用程序则返回其指针
event->setDropAction(Qt::MoveAction);//然后设置接受 Qt::MoveAction 类型的拖动
event->accept();
}
}
//dragMoveEvent() 则和这个函数具有相同的代码,因为我们需要重写拖动移动的代码。
void ProjectListWidget::dragMoveEvent(QDragMoveEvent *event)
{
ProjectListWidget *source =
qobject_cast<ProjectListWidget *>(event->source());
if (source && source != this) {
event->setDropAction(Qt::MoveAction);
event->accept();
}
}

void ProjectListWidget::dropEvent(QDropEvent *event)
{
ProjectListWidget *source =
qobject_cast<ProjectListWidget *>(event->source());
if (source && source != this) {
addItem(event->mimeData()->text());
//我们取出 QDrag 中的 mimeData 数据,调用 addItem() 添加到当前的列表中
event->setDropAction(Qt::MoveAction);
event->accept();
}
}