目录
创作背景
写这篇文章主要有一下几点原因。第一个呢就是小白学习qt,准备实现拖拽效果但是不会写。再一个就是在网上找到的教程都是参差不齐,没找到特别详细的,对小白友好的教程。所以在研究透彻之后供大家参考。有不正确的地方还请大家指正。
开发环境
QT5.12.2 + win11 +minggw73
运行效果
实现原理
1.参考文档
MimaData文档https://doc.qt.io/archives/qt-5.5/qmimedata.html#setImageData
2.主要原理
以QLabel为例,当鼠标按住QLabel会触发mousePressEvent(QMouseEvent *a_event)事件
,当你按住这个QLabel拖动一段距离时,会触发mouseMoveEvent(QMouseEvent *a_event)
事件。当鼠标拖动一个QLabel进入另外一个QLabel【也可以是它自己】时,会触发dragEnterEvent(QDragEnterEvent *a_event)事件,当鼠标拖动一个QLabel进入另外一个QLabel【也可以是它自己】并且松开鼠标时会触发dropEvent(QDropEvent *a_event)。
但是,QLabel封装的时候并没有在这几个事件触发时添加处理逻辑。所以需要创建一个QLabel的子类,来重写这些事件函数,并且添加处理逻辑。
好了,到此为止。需要用到的主要事件和在哪里触发就说完了。
实现过程
1.首先是重写QLabel
.h头文件
#ifndef DROPQLABEL_H
#define DROPQLABEL_H
#include<QLabel>
#include<QDragEnterEvent>
#include<QMimeData>
#include<QDrag>
#include<QDebug>
#include<QApplication>
class DropQLabel : public QLabel//公开继承QLabel
{
Q_OBJECT
public:
DropQLabel(QWidget *parent = nullptr);
~DropQLabel();
//重写鼠标放下时事件处理函数
void dropEvent(QDropEvent* a_event);
//重写鼠标拖入时事件处理函数
void dragEnterEvent(QDragEnterEvent* a_event);
//重写鼠标按住时事件处理函数
void mousePressEvent(QMouseEvent *a_event);
//重写鼠标移动时事件处理函数
void mouseMoveEvent(QMouseEvent *a_event);
};
#endif // DROPQLABEL_H
.cpp文件
#include "dropqlabel.h"
DropQLabel::DropQLabel(QWidget *parent):QLabel(parent)//调用父类的构造函数
{
//构造函数中可以没有内容,但是必须实现
}
DropQLabel::~DropQLabel()
{
//析构函数也是,可以没有内容但是必须实现
}
//鼠标放下的事件
void DropQLabel::dropEvent(QDropEvent *a_event)
{
QString a="我接受到拖拽内容了,内容是:"+a_event->mimeData()->text();//解析mamiData中携带的信息
qDebug()<<a;
}
//鼠标拖入的事件
void DropQLabel::dragEnterEvent(QDragEnterEvent *a_event)
{
// 如果拖动的事件中有Text,则允许drop。如果没有Text则不允许放下
if (a_event->mimeData()->hasText())
{
// 如果未调用,则无法drop
a_event->acceptProposedAction();
}
}
void DropQLabel::mousePressEvent(QMouseEvent *a_event)
{
}
void DropQLabel::mouseMoveEvent(QMouseEvent *a_event)
{
if (a_event->buttons() & Qt::LeftButton)//判断是否时鼠标的事件,且为左键则执行
{
QApplication::startDragDistance())
//Qt中拖拽时需要生成一个Drag对象,才能实现拖拽
这些事件声明也可以放在mousePressEvent(QMouseEvent *a_event)函数中
QDrag *drag = new QDrag(this);
//拖拽时也必须声明一个MimeData可以用来传递信息,如果不需要传递信息也要声明并且调用drag的setMimeData()函数,否则会报错。
QMimeData *mimeData = new QMimeData;
QString labelText=this->text();
QString a="我开始被拖拽了,发送的拖拽内容是:"+this->text();
this->setText(a);
//可以调用mimeData的各种方法设置想要mimeData传递的信息
mimeData->setText(labelText);
drag->setMimeData(mimeData);
drag->exec();//最后调用exec()即可
}
}
QLabel的重写工作完成之后,也就完成了大半。
2.第二步是使用自己写的Label类
在QtCreator的ui编辑器中拖入一个QLabel右键单击,在快捷菜单中选择“提升为”选项。
在弹出的对话框中输入类名,点击添加
添加成功后选中类,点击对话框底部的提升按钮。
看到下图处,类名改变则表示提升成功。
最后在mainWindow的cpp代码构造函数中允许放下的动作setAcceptDrops(true);
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
DropQLabel* aa=this->findChild<DropQLabel *>("bbb");
DropQLabel* bb=this->findChild<DropQLabel *>("aaa");
//设置允许放下动作
bb->setAcceptDrops(true);
//再设置父UI框架为允许放下,否则会失败。
this->setAcceptDrops(true);
}
MainWindow::~MainWindow()
{
delete ui;
}
至此,所有工作已经完成。
总结
大致步骤就是:重写QLabel=>使用自己写的控件=>在主窗口中设置允许鼠标放下动作。
然后就是:
Qt开发任重道远,加油吧!!