一、效果示例图
提示:主控件(CDragTest界面,UI中中包含CWidget界面);子控件(CWidget界面,在CDragTest界面添加)
提示:源码中拖拽数据设置的文本不同,是博主准备好示例素材之后添加的,但是在控件自己对应的拖拽事件中,发送的数据就是控件自己对应的数据。
1.同一窗口
在同一窗口中操作,主控件接收Drop,子控件不接收Drop,在窗口中的拖动事件主控件都会响应接收;
在同一窗口中操作,主控件不接收Drop,子控件接收Drop,在窗口中的拖动事件子控件只接收子控件所占位置的事件;
在同一窗口中操作,主控件不接收Drop,子控件也不接收Drop,在窗口中的拖动事件都不会接收;
在同一窗口中操作,主控件接收Drop,子控件也接收Drop,在窗口中的拖动事件主子控件都会响应,但是仅会响应自己包含的拖动区域;
2.不同窗口(效果和同意窗口一致)
在不同窗口中操作,所有控件都接收,在窗口中的拖动事件都会接收拖动事件;
在不同窗口中操作,所有控件都不接收,在窗口中的拖动事件都不接收拖动事件;
提示:不会使用Qt设计师设计界面的小伙伴点击这里
二、QDrag须知(个人理解)
- 拖拽事件在操作系统中非常常见,如选择文本后的拖动,选择文件后的拖动等;
- 要触发QDrag需要通过该对象的exec()函数主动触发,且该函数会阻塞当前线程(可查看源码中mousePressEvent源码);
- 要使拖动操作中包含数据需要创建QMimeData对象,并将数据(支持多种数据类型如URL、TEXT、IMAGE,详情可查看Qt源码)设置到该对象中,然后将该对象设置到QDrag中;
- 控件对象如果需要响应拖拽事件,需要调用setAcceptDrops()函数接收拖拽事件;
- 在dragEnterEvent需要主动调用accept()函数,否则dragMoveEvent、dragLeaveEvent两个事件都不会进入。
三、源码
CWidget.h
#ifndef CWIDGET_H
#define CWIDGET_H
#include <QWidget>
namespace Ui {
class CWidget;
}
class CWidget : public QWidget
{
Q_OBJECT
public:
explicit CWidget(QWidget *parent = nullptr);
~CWidget();
// QWidget interface
protected:
/**
* @brief dragEnterEvent 拖拽进入事件
* @param event 拖拽事件对象
*/
void dragEnterEvent(QDragEnterEvent *event);
/**
* @brief dragMoveEvent 拖拽移动事件
* @param event 拖拽事件对象
*/
void dragMoveEvent(QDragMoveEvent *event);
/**
* @brief dragLeaveEvent 拖拽离开事件
* @param event 拖拽事件对象
*/
void dragLeaveEvent(QDragLeaveEvent *event);
/**
* @brief dropEvent 方向事件
* @param event 放下事件对象
*/
void dropEvent(QDropEvent *event);
/**
* @brief mousePressEvent 鼠标按下事件
* @param event 鼠标事件对象
*/
void mousePressEvent(QMouseEvent *event);
private slots:
/**
* @brief on_dragFlagBtn_clicked 按钮点击槽函数
* @param checked 选中状态
*/
void on_dragFlagBtn_clicked(bool checked);
private:
Ui::CWidget *ui;
};
#endif // CWIDGET_H
CWidget.cpp
#include "CWidget.h"
#include "ui_CWidget.h"
#include <QDrag>
#include <QDebug>
#include <QMimeData>
#include <QDragMoveEvent>
CWidget::CWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::CWidget)
{
ui->setupUi(this);
}
CWidget::~CWidget()
{
delete ui;
}
void CWidget::dragEnterEvent(QDragEnterEvent *event)
{
// 事件接收拖拽
event->accept();
// 函数名追加到文本编辑框中
ui->textEdit->append(__func__);
}
void CWidget::dragMoveEvent(QDragMoveEvent *event)
{
// 函数名追加到文本编辑框中
ui->textEdit->append(__func__);
}
void CWidget::dragLeaveEvent(QDragLeaveEvent *event)
{
// 函数名追加到文本编辑框中
ui->textEdit->append(__func__);
}
void CWidget::dropEvent(QDropEvent *event)
{
// 获取QMimeData对象中的文本
QString text = event->mimeData()->text();
// 函数名追加到文本编辑框中
ui->textEdit->append(text);
}
void CWidget::mousePressEvent(QMouseEvent *event)
{
// 判断当前按钮是否为左键
bool mouseBtn = Qt::LeftButton == event->button();
// 如果是则进入
if(mouseBtn)
{
// 创建QDrag对象
QDrag *drag = new QDrag(this);
// 创建拖拽对象包含的数据
QMimeData *data = new QMimeData;
// 设置数据文本
data->setText("Child Wieget 拖拽操作");
// 将数据设置到拖拽对象中
drag->setMimeData(data);
// 函数名追加到文本编辑框中
ui->textEdit->append(QString("%1 拖拽操作开始").arg(__func__));
// 执行拖拽对象
drag->exec();
ui->textEdit->append(QString("%1 拖拽操作结束").arg(__func__));
}
}
void CWidget::on_dragFlagBtn_clicked(bool checked)
{
// 通过按钮选中状态切换控件接收拖拽的状态
this->setAcceptDrops(checked);
}
CWidget.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CWidget</class>
<widget class="QWidget" name="CWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<item>
<widget class="QPushButton" name="dragFlagBtn">
<property name="text">
<string>Drag Flag</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QTextEdit" name="textEdit"/>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
CDragTest.h
#ifndef CDRAGTEST_H
#define CDRAGTEST_H
#include <QWidget>
namespace Ui {
class CDragTest;
}
class CDragTest : public QWidget
{
Q_OBJECT
public:
explicit CDragTest(QWidget *parent = nullptr);
~CDragTest();
// QWidget interface
protected:
/**
* @brief dragEnterEvent 拖拽进入事件
* @param event 拖拽事件对象
*/
void dragEnterEvent(QDragEnterEvent *event);
/**
* @brief dragMoveEvent 拖拽移动事件
* @param event 拖拽事件对象
*/
void dragMoveEvent(QDragMoveEvent *event);
/**
* @brief dragLeaveEvent 拖拽离开事件
* @param event 拖拽事件对象
*/
void dragLeaveEvent(QDragLeaveEvent *event);
/**
* @brief dropEvent 方向事件
* @param event 放下事件对象
*/
void dropEvent(QDropEvent *event);
/**
* @brief mousePressEvent 鼠标按下事件
* @param event 鼠标事件对象
*/
void mousePressEvent(QMouseEvent *event);
private slots:
/**
* @brief on_dragFlagBtn_clicked 按钮点击槽函数
* @param checked 选中状态
*/
void on_dragFlagBtn_clicked(bool checked);
private:
Ui::CDragTest *ui;
};
#endif // CDRAGTEST_H
CDragTest.cpp
#include "CDragTest.h"
#include "ui_CDragTest.h"
#include <QWidget>
#include <QDrag>
#include <QDebug>
#include <QMimeData>
#include <QDragMoveEvent>
CDragTest::CDragTest(QWidget *parent) :
QWidget(parent),
ui(new Ui::CDragTest)
{
ui->setupUi(this);
// 初始化设置接收拖拽
this->setAcceptDrops(true);
}
CDragTest::~CDragTest()
{
delete ui;
}
void CDragTest::dragEnterEvent(QDragEnterEvent *event)
{
// 事件接收拖拽
event->accept();
// 函数名追加到文本编辑框中
ui->textEdit->append(__func__);
}
void CDragTest::dragMoveEvent(QDragMoveEvent *event)
{
// 函数名追加到文本编辑框中
ui->textEdit->append(__func__);
}
void CDragTest::dragLeaveEvent(QDragLeaveEvent *event)
{
// 函数名追加到文本编辑框中
ui->textEdit->append(__func__);
}
void CDragTest::dropEvent(QDropEvent *event)
{
// 获取QMimeData对象中的文本
QString text = event->mimeData()->text();
// 函数名追加到文本编辑框中
ui->textEdit->append(text);
}
void CDragTest::mousePressEvent(QMouseEvent *event)
{
// 判断当前按钮是否为左键
bool mouseBtn = Qt::LeftButton == event->button();
// 如果是则进入
if(mouseBtn)
{
// 创建QDrag对象
QDrag *drag = new QDrag(this);
// 创建拖拽对象包含的数据
QMimeData *data = new QMimeData;
// 设置数据文本
data->setText("Main Widget 拖拽操作");
// 将数据设置到拖拽对象中
drag->setMimeData(data);
// 函数名追加到文本编辑框中(拖拽开始标志)
ui->textEdit->append(QString("%1 拖拽操作开始").arg(__func__));
// 执行拖拽对象
drag->exec();
// 函数名追加到文本编辑框中(拖拽结束标志)
ui->textEdit->append(QString("%1 拖拽操作结束").arg(__func__));
}
}
void CDragTest::on_dragFlagBtn_clicked(bool checked)
{
// 通过按钮选中状态切换控件接收拖拽的状态
this->setAcceptDrops(checked);
}
CDragTest.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CDragTest</class>
<widget class="QWidget" name="CDragTest">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>429</width>
<height>336</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPushButton" name="dragFlagBtn">
<property name="text">
<string>Drag Flag</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QTextEdit" name="textEdit"/>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="CWidget" name="widget" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>CWidget</class>
<extends>QWidget</extends>
<header>CWidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
main.cpp
#include "CDragTest.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
CDragTest w1;
w1.show();
CDragTest w2;
w2.show();
return a.exec();
}
总结
拖拽事件在实际生活中非常实用,除了普通的操作以外,还可以通过不同数据分辨实现不同的操作。
友情提示——哪里看不懂可私哦,让我们一起互相进步吧
(创作不易,请留下一个免费的赞叭 谢谢 ^o^/)
注:文章为作者编程过程中所遇到的问题和总结,内容仅供参考,若有错误欢迎指出。
注:如有侵权,请联系作者删除