QT拖拽事件

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);
    }
}

  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Qt 中,拖拽事件需要重写 QWidget 或其子类的以下方法: 1. void mousePressEvent(QMouseEvent *event):当鼠标按下时触发,通常在此方法中开始拖拽操作。 2. void mouseMoveEvent(QMouseEvent *event):当鼠标移动时触发,通常在此方法中更新拖拽操作的状态。 3. void mouseReleaseEvent(QMouseEvent *event):当鼠标释放时触发,通常在此方法中结束拖拽操作。 下面是一个简单的示例,演示了如何在一个 QLabel 控件中实现拖拽操作: ```cpp #include <QLabel> #include <QMouseEvent> class DragLabel : public QLabel { public: DragLabel(QWidget *parent = nullptr) : QLabel(parent) {} protected: void mousePressEvent(QMouseEvent *event) override { if (event->button() == Qt::LeftButton) { // 开始拖拽操作 QDrag *drag = new QDrag(this); QMimeData *mimeData = new QMimeData; mimeData->setText(text()); drag->setMimeData(mimeData); drag->exec(Qt::MoveAction); } } void mouseMoveEvent(QMouseEvent *event) override { if (event->buttons() & Qt::LeftButton) { // 更新拖拽状态 QPixmap pixmap = grab(); QDrag *drag = new QDrag(this); QMimeData *mimeData = new QMimeData; mimeData->setText(text()); drag->setMimeData(mimeData); drag->setPixmap(pixmap); drag->setHotSpot(event->pos()); drag->exec(Qt::MoveAction); } } void mouseReleaseEvent(QMouseEvent *event) override { // 结束拖拽操作 QLabel::mouseReleaseEvent(event); } }; ``` 在上面的代码中,我们重写了 QWidget 的三个方法,分别是 mousePressEvent、mouseMoveEvent 和 mouseReleaseEvent。在 mousePressEvent 中,我们创建了一个 QDrag 对象,并将文本数据设置为拖拽操作的数据类型。在 mouseMoveEvent 中,我们更新了拖拽操作的状态,并将 QWidget 转换为 QPixmap,作为 QDrag 的图像数据。在 mouseReleaseEvent 中,我们不需要做任何事情,只需要调用 QLabel 的 mouseReleaseEvent 方法即可。 使用 DragLabel 控件时,只需要将它添加到窗口中即可: ```cpp DragLabel *label = new DragLabel("Drag me", this); label->setAlignment(Qt::AlignCenter); label->setFixedSize(100, 50); label->move(50, 50); label->show(); ``` 这样,当用户按下鼠标左键并移动时,就会触发拖拽操作。在拖拽过程中,QLabel 控件会跟随鼠标移动,并在释放鼠标左键时结束拖拽操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值