Qt拖放操作

“拖放操作”,顾名思义,就是由“拖动”和“放置”两个动作完成的。在Qt中,实现拖放的操作需要借助类QDrag和QDrop来完成。以下通过树形结构控件来描述Qt的拖放操作的过程。

1. 首先,需要设置自己的控件是支持拖放操作的,按照如下设置即可:

setDragEnabled(true);   //允许拖拽
setAcceptDrops(true);   //允许放置

2. 其次,我这个拖放操作是基于QTreeView来完成的,因此继承这个QTeeView之后还需要实现startDrag()这个函数。它可以被理解成是拖放操作的入口函数。

//开始拖拽事件
virtual void stratDrag(Qt::DropActions supportedAxtions);

//这个函数可以理解为拖放操作的入口函数。当拖放开始进行时,就会发现断点会进到这里。
void CMyTree::stratDrag(Qt::DropActions supportedAxtions)
{
	QDrag* pDrag = new QDrag(this);
	QMimeData* pMimeData = new QMimeData;
	QModelIndex index = currentIndex();
	
	if (pDrag && pMimeData)
	{
		pDrag->setMimeData(pMimeData);
		pDrag->exec(Qt::MoveAction);
	}
}

3. 接下来,拖放操作肯定是离不开鼠标的按压与移动的。因此还需要实现以下几个虚函数。

//鼠标点击事件
	virtual void mousePressEvent(QMouseEvent *event);
	//拖拽进入事件
	virtual void dragEnterEvent(QDragEnterEvent* event);
	//拖拽移动事件
	virtual void dragMoveEvent(QDragMoveEvent* event);
	//拖放事件
	virtual void dropEvent(QDropEvent *event);
	//鼠标松开事件
	virtual void mouseReleaseEvent(QMouseEvent *event);
	//鼠标移动事件
	virtual void mouseMoveEvent(QMouseEvent *event);
	//鼠标悬停事件
	virtual bool viewportEvent(QEvent *event);

当一切准备工作完成后,再通过QTreeView与QStandardItemModel相结合,完成一些列的拖放操作。本例大致需求是:将叶子节点拖放到不同组织下。整个源码如下:

//CMyTree.h
#pragma once
#include 
#include 

class CMyTree :
	public QTreeView
{
public:
	CMyTree(QWidget* parent = nullptr);
protected:
	//开始拖拽事件
	virtual void stratDrag(Qt::DropActions supportedAxtions);
	//鼠标点击事件
	virtual void mousePressEvent(QMouseEvent *event);
	//拖拽进入事件
	virtual void dragEnterEvent(QDragEnterEvent* event);
	//拖拽移动事件
	virtual void dragMoveEvent(QDragMoveEvent* event);
	//拖放事件
	virtual void dropEvent(QDropEvent *event);
	//鼠标松开事件
	virtual void mouseReleaseEvent(QMouseEvent *event);
	//鼠标移动事件
	virtual void mouseMoveEvent(QMouseEvent *event);
	//鼠标悬停事件
	virtual bool viewportEvent(QEvent *event);
private:
	QStandardItem* m_pDragItem;
	QStandardItem* m_pDropItem;
};
//CMyTree.cpp
#include "CMyTree.h"
#include 
#include 
#include 
#include 

CMyTree::CMyTree(QWidget* parent /* = nullptr */)
	: QTreeView(parent)
	, m_pDragItem(nullptr)
	, m_pDropItem(nullptr)
{
	setDropIndicatorShown(true);
	setHeaderHidden(true);  //隐藏表头
	setDragEnabled(true);   //允许拖拽
	setAcceptDrops(true);   //允许放置
}

void CMyTree::stratDrag(Qt::DropActions supportedAxtions)
{
	QDrag* pDrag = new QDrag(this);
	QMimeData* pMimeData = new QMimeData;
	QModelIndex index = currentIndex();
	
	if (pDrag && pMimeData)
	{
		pDrag->setMimeData(pMimeData);
		pDrag->exec(Qt::MoveAction);
	}
}

void CMyTree::mousePressEvent(QMouseEvent *event)
{
	if (Qt::RightButton == event->button())
	{
		setDragEnabled(false);
	}
	else if (Qt::LeftButton == event->button())
	{
		setDragEnabled(true);
	}
	QTreeView::mousePressEvent(event);
}

void CMyTree::dragEnterEvent(QDragEnterEvent* event)
{
	if (event->mimeData())
	{
		QStandardItemModel* pModel = (QStandardItemModel*)(this->model());
		QPoint mousePos = event->pos();
		QModelIndex localIndex = indexAt(mousePos);
		m_pDragItem = pModel->itemFromIndex(localIndex);
		QString strData = localIndex.data(Qt::DisplayRole).toString();
		QRect rect = visualRect(localIndex);
		event->accept();
	}
}

void CMyTree::dragMoveEvent(QDragMoveEvent* event)
{
	if (event->mimeData())
	{
		update();
		event->accept();
	}
}

void CMyTree::dropEvent(QDropEvent *event)
{
	QStandardItemModel* pModel = (QStandardItemModel*)(this->model());
	QPoint mousePos = event->pos();
	QModelIndex localIndex = indexAt(mousePos);
	m_pDropItem = pModel->itemFromIndex(localIndex);
	QString strData = localIndex.data(Qt::DisplayRole).toString();
	QRect rect = visualRect(localIndex);

	//同组织下释放没效果
	QStandardItem* pDragItemParent = m_pDragItem->parent();
	QStandardItem* pDropItemParent = m_pDropItem->parent();
	if (pDragItemParent == pDropItemParent)
	{
		return;
	}
	else if (pDragItemParent && pDropItemParent)
	{
		QStandardItem* pItem = new QStandardItem(m_pDragItem->data(Qt::DisplayRole).toString());
		pDropItemParent->appendRow(pItem);
	}
	update();
}

void CMyTree::mouseReleaseEvent(QMouseEvent *event)
{
	QTreeView::mouseReleaseEvent(event);
}

void CMyTree::mouseMoveEvent(QMouseEvent *event)
{
	QTreeView::mouseMoveEvent(event);
}

bool CMyTree::viewportEvent(QEvent *event)
{
	return QTreeView::viewportEvent(event);
}
//CMyApp.h
#pragma once

#include 
#include 
#include "ui_CMyApp.h"

class CMyApp : public QWidget
{
	Q_OBJECT

public:
	CMyApp(QWidget *parent = Q_NULLPTR);
	void InitUI();

private:
	Ui::CMyAppClass ui;
	QStandardItemModel* m_pModel;
};
//CMyApp.cpp
#include "CMyApp.h"
#include 

CMyApp::CMyApp(QWidget *parent)
	: QWidget(parent)
{
	ui.setupUi(this);
	m_pModel = new QStandardItemModel(ui.treeView);
	InitUI();
}

void CMyApp::InitUI()
{
	QStandardItem* pItem1 = new QStandardItem(QStringLiteral("法师"));
	m_pModel->appendRow(pItem1);
	QStandardItem* pItem1_1 = new QStandardItem(QStringLiteral("妲己"));
	QStandardItem* pItem1_2 = new QStandardItem(QStringLiteral("小乔"));
	QStandardItem* pItem1_3 = new QStandardItem(QStringLiteral("西施"));
	pItem1->appendRow(pItem1_1);
	pItem1->appendRow(pItem1_2);
	pItem1->appendRow(pItem1_3);

	QStandardItem* pItem2 = new QStandardItem(QStringLiteral("法刺"));
	m_pModel->appendRow(pItem2);
	QStandardItem* pItem2_1 = new QStandardItem(QStringLiteral("不知火舞"));
	QStandardItem* pItem2_2 = new QStandardItem(QStringLiteral("貂蝉"));
	QStandardItem* pItem2_3 = new QStandardItem(QStringLiteral("上官婉儿"));
	pItem2->appendRow(pItem2_1);
	pItem2->appendRow(pItem2_2);
	pItem2->appendRow(pItem2_3);

	ui.treeView->setModel(m_pModel);
}

//main.cpp
#include "CMyApp.h"
#include 

int main(int argc, char *argv[])
{
	QApplication a(argc, argv);
	CMyApp w;
	w.show();
	return a.exec();
}

你可能感兴趣的:(QT,C++,qt,c++,开发语言)