QT拖拽事件
先讲解一下大致需求,有两个窗体,当我点击其中一个窗体中的lable时,开始拖拽,拖拽到另一个中,创建于拖拽一样的lable。
实现思路:
1,鼠标按下。
2,开始拖拽
3.拖拽进入另一个窗体。
4.鼠标放开(其实是拖拽结束),生成lable。
接下来开始一步步实现。希望能帮助你。
首先在实现之前要明确一个事情,就是实现是基于两个窗体还是一个窗体,如果是一个窗体内(指的是不带有嵌套的那种,其实不用实现拖拽事件,而是鼠标点击和鼠标松下事件。),所以今天实现的拖拽事件是在两个窗体之间实现的。
一 前期准备工作
为了展示效果,我在两个窗体类(MyDragWidget)中都各自放置了四个小汽车,效果如下,
代码如下:
setAcceptDrops(true);///允许拖动事件 至关重要
///创建4个lable存放图片
QLabel* lable1 = new QLabel(this);
lable1->setPixmap(QPixmap(":png/1.png"));
lable1->move(0,0);///放在指定位置
QLabel* lable12 = new QLabel(this);
lable12->setPixmap(QPixmap(":png/01.png"));
lable12->move(100,0);
QLabel* lable13 = new QLabel(this);
lable13->setPixmap(QPixmap(":png/12.png"));
lable13->move(100,100);
QLabel* lable14 = new QLabel(this);
lable14->setPixmap(QPixmap(":png/13.png"));
lable14->move(0,100);
二 重载鼠标按下事件
1.重载父类的mousePressEvent函数。
/**
* @brief 鼠标按下事件
* @param QMouseEvent
* @return 无
*/
void mousePressEvent(QMouseEvent *event) override;
那么我们想要实现鼠标按下事件中需要完成的事情是什么?
(1)获取当前点击小汽车的信息,也就是图片信息。
(2)保存到一个地方,供我们在另一个窗体中获取,且创建出来。
我们先实现第一步,获取当前lable小汽车信息:
///获取带你给前点击的子控件 Qlabel
QLabel *child = static_cast<QLabel*>(childAt(event->pos()));
if (!child)
return;
QPixmap pixmap = *child->pixmap(); ///图像处理类
这样我们就获取了当前lable的图片信息。
实现第二步,保存下来:
QByteArray itemData;
QDataStream dataStream(&itemData, QIODevice::WriteOnly);
dataStream << pixmap << QPoint(event->pos() - child->pos());///添加光标位置、和鼠标位置
//! [1]
//! [2]
QMimeData *mimeData = new QMimeData;
mimeData->setData("application/x-dnditemdata", itemData);
//! [2]
//! [3]
QDrag *drag = new QDrag(this); ///鼠标拖拽事件
drag->setMimeData(mimeData); ///设置选择节点信息等
drag->setPixmap(pixmap); ///设置鼠标移动时的样式
drag->setHotSpot(event->pos() - child->pos());
//! [3]
QPixmap tempPixmap = pixmap;
QPainter painter;
painter.begin(&tempPixmap);
painter.fillRect(pixmap.rect(), QColor(127, 127, 127, 127));
painter.end();
child->setPixmap(tempPixmap);
if (drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction) == Qt::MoveAction)
{
child->close();
}
else
{
child->show();
child->setPixmap(pixmap);
}
2.开始记录实现dragEnterEvent函数,开始拖拽。
if (event->mimeData()->hasFormat("application/x-dnditemdata"))
{
if (event->source() == this)
{
event->setDropAction(Qt::MoveAction);
event->accept();
}
else
{
event->acceptProposedAction();
}
}
else
{
event->ignore();
}
3开始实现dragMoveEvent函数
if (event->mimeData()->hasFormat("application/x-dnditemdata"))
{
if (event->source() == this)
{
event->setDropAction(Qt::MoveAction);
event->accept();
} else
{
event->acceptProposedAction();
}
}
else
{
event->ignore();
}
最后实现dropEvent函数,创建新的lable。或者将原先的lable换位置。
if (event->mimeData()->hasFormat("application/x-dnditemdata"))
{
QByteArray itemData = event->mimeData()->data("application/x-dnditemdata");
QDataStream dataStream(&itemData, QIODevice::ReadOnly);
QPixmap pixmap;
QPoint offset;
dataStream >> pixmap >> offset;
QLabel *newIcon = new QLabel(this);
newIcon->setPixmap(pixmap);
newIcon->move(event->pos() - offset);
newIcon->show();
newIcon->setAttribute(Qt::WA_DeleteOnClose);
if (event->source() == this)
{
event->setDropAction(Qt::MoveAction);
event->accept();
}
else
{
event->acceptProposedAction();
}
}
else
{
event->ignore();
}
最终实现代码
.h
#ifndef MYDRAGWIDGET_H
#define MYDRAGWIDGET_H
#include <QWidget>
class QDragEnterEvent;
class QDropEvent;
namespace Ui {
class MyDragWidget;
}
class MyDragWidget : public QWidget
{
Q_OBJECT
public:
MyDragWidget(QWidget *parent = nullptr);
~MyDragWidget();
void setName(QString name);
protected:
void dragEnterEvent(QDragEnterEvent *event) override;
void dragMoveEvent(QDragMoveEvent *event) override;
void dropEvent(QDropEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
private:
Ui::MyDragWidget *ui;
QString m_name ;
};
#endif // MYDRAGWIDGET_H
.cpp
#include "MyDragWidget.h"
#include "ui_MyDragWidget.h"
#include <QMouseEvent>
#include <QDragEnterEvent>
#include <QDebug>
#include <QLabel>
#include <QMimeData>
#include <QDrag>
#include <QPainter>
MyDragWidget::MyDragWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::MyDragWidget)
{
ui->setupUi(this);
//setMinimumSize(200, 200);
setAcceptDrops(true);///允许拖动事件
///创建4个lable存放图片
QLabel* lable1 = new QLabel(this);
lable1->setPixmap(QPixmap(":png/1.png"));
lable1->move(0,0);///放在指定位置
QLabel* lable12 = new QLabel(this);
lable12->setPixmap(QPixmap(":png/01.png"));
lable12->move(100,0);
QLabel* lable13 = new QLabel(this);
lable13->setPixmap(QPixmap(":png/12.png"));
lable13->move(100,100);
QLabel* lable14 = new QLabel(this);
lable14->setPixmap(QPixmap(":png/13.png"));
lable14->move(100,100);
}
void MyDragWidget::setName(QString name)
{
m_name = name;
}
MyDragWidget::~MyDragWidget()
{
delete ui;
}
void MyDragWidget::dragEnterEvent(QDragEnterEvent *event)
{
qDebug()<<"4"<<m_name;
if (event->mimeData()->hasFormat("application/x-dnditemdata"))
{
if (event->source() == this)
{
event->setDropAction(Qt::MoveAction);
event->accept();
}
else
{
event->acceptProposedAction();
}
}
else
{
event->ignore();
}
}
void MyDragWidget::dragMoveEvent(QDragMoveEvent *event)
{
qDebug()<<"3"<<m_name;
if (event->mimeData()->hasFormat("application/x-dnditemdata"))
{
if (event->source() == this)
{
event->setDropAction(Qt::MoveAction);
event->accept();
} else
{
event->acceptProposedAction();
}
}
else
{
event->ignore();
}
}
void MyDragWidget::dropEvent(QDropEvent *event)///落下创建Qlabel
{
qDebug()<<"2"<<m_name;
if (event->mimeData()->hasFormat("application/x-dnditemdata"))
{
QByteArray itemData = event->mimeData()->data("application/x-dnditemdata");
QDataStream dataStream(&itemData, QIODevice::ReadOnly);
QPixmap pixmap;
QPoint offset;
dataStream >> pixmap >> offset;
QLabel *newIcon = new QLabel(this);
newIcon->setPixmap(pixmap);
newIcon->move(event->pos() - offset);
newIcon->show();
newIcon->setAttribute(Qt::WA_DeleteOnClose);
if (event->source() == this)
{
event->setDropAction(Qt::MoveAction);
event->accept();
}
else
{
event->acceptProposedAction();
}
}
else
{
event->ignore();
}
}
//! [1]
void MyDragWidget::mousePressEvent(QMouseEvent *event)
{
qDebug()<<"1"<<m_name;
QLabel *child = static_cast<QLabel*>(childAt(event->pos()));///获取带你给前点击的子控件 Qlabel
if (!child)
return;
QPixmap pixmap = *child->pixmap(); ///图像处理类
QByteArray itemData;
QDataStream dataStream(&itemData, QIODevice::WriteOnly);
dataStream << pixmap << QPoint(event->pos() - child->pos());///添加光标位置、和鼠标位置
//! [1]
//! [2]
QMimeData *mimeData = new QMimeData;
mimeData->setData("application/x-dnditemdata", itemData);
//! [2]
//! [3]
QDrag *drag = new QDrag(this); ///鼠标拖拽事件
drag->setMimeData(mimeData); ///设置选择节点信息等
drag->setPixmap(pixmap); ///设置鼠标移动时的样式
drag->setHotSpot(event->pos() - child->pos());
//! [3]
QPixmap tempPixmap = pixmap;
QPainter painter;
painter.begin(&tempPixmap);
painter.fillRect(pixmap.rect(), QColor(127, 127, 127, 127));
painter.end();
child->setPixmap(tempPixmap);
if (drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction) == Qt::MoveAction)
{
child->close();
}
else
{
child->show();
child->setPixmap(pixmap);
}
}