Qt拖拽事件,实现控件内项的相互拖拽

文章目录

这里主要以QTableview控件为例,实现表格内数据的相互拖拽。

1拖拽演示

2 步骤

自定以QTableView类,在自定义类中重写拖拽事件:

cpp 复制代码
void dropEvent(QDropEvent *event);
void dragEnterEvent(QDragEnterEvent *event);
void dragMoveEvent(QDragMoveEvent *event);
void dragLeaveEvent(QDragLeaveEvent *event);

实现自定义的QTableView,在鼠标点击项的时候,构造一个图片,模拟出项被拖动的样子,通过

QMimeData来传递数据,QDrag会触发表格的进入事件,在进入事件内出入一个新的项,并通过发送信号的对象,来通过指针删除原来的项,大概思路就是这样。

3 实现

cpp 复制代码
#include <QTableView>
#include <QStandardItemModel>
#include <QDropEvent>
#include <QMouseEvent>
#include <QDragEnterEvent>
#include<QByteArray>
class CTableView : public QTableView
{
	Q_OBJECT

public:
	CTableView(QWidget *parent);
	~CTableView();
public:
	void insertNewItem(QString str);
	void setHorizontalHeaderName(QString _name);
	bool removeItem(QString str);
	void dropEvent(QDropEvent *event);
	void dragEnterEvent(QDragEnterEvent *event);
	void dragMoveEvent(QDragMoveEvent *event);
	void dragLeaveEvent(QDragLeaveEvent *event);
private:

	void slotItemPressed(const QModelIndex &index);
private:
	QStandardItemModel*		m_model;
};
cpp 复制代码
#include "ctableview.h"
#include <QHeaderView>
#include <QPainter>
#include <QMimeData>
#include <QDrag>
#include <QDebug>
CTableView::CTableView(QWidget *parent)
	: QTableView(parent)
{
	setAcceptDrops(true);
	m_model = new QStandardItemModel();
	this->setModel(m_model);
	this->verticalHeader()->setVisible(false);
	this->setEditTriggers(QAbstractItemView::NoEditTriggers);
	connect(this, &CTableView::pressed, this, &CTableView::slotItemPressed);
}

CTableView::~CTableView()
{

}

void CTableView::insertNewItem(QString str)
{
	int t_row = m_model->rowCount();
	QStandardItem* t_item = new QStandardItem(str);
	
	m_model->setItem(t_row, 0, t_item);
	m_model->item(t_row, 0)->setTextAlignment(Qt::AlignHCenter);
	m_model->item(t_row, 0)->setBackground(QColor(187, 203, 233));
}

void CTableView::setHorizontalHeaderName(QString _name)
{
	m_model->setHorizontalHeaderLabels(QStringList(_name));
	this->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);// 设置表头调整模式为 Stretch
	this->horizontalHeader()->setStretchLastSection(true);// 将最后一列拉伸到表格宽度
	this->horizontalHeader()->setStyleSheet("QHeaderView::section {"
		"color: rgb(32,159,223);padding-left: 4px;border: 1px solid #6c6c6c;}");
}


bool CTableView::removeItem(QString str)
{
	for (int row = 0; row < m_model->rowCount(); row++)
	{
		if (m_model->item(row, 0)->text() == str)
		{
			return m_model->removeRow(row);
		}
	}
	return false;
}

void CTableView::dropEvent(QDropEvent *event)
{
	if (!event->mimeData()->hasText()) { // 修改判断条件
		return;
	}
	insertNewItem(event->mimeData()->text());
	CTableView* tableView = qobject_cast<CTableView*>(event->source());
	if (tableView == nullptr)
	{
		return;
	}
	tableView->removeItem(event->mimeData()->text());
}

void CTableView::dragEnterEvent(QDragEnterEvent *event)
{
	//这个函数的主要作用是根据拖动数据中是否包含文本,决定是否接受拖放操作,并将操作类型设置为建议类型。
	if (event->mimeData()->hasText()) { // 修改判断条件
		event->acceptProposedAction();
	}
}


void CTableView::dragMoveEvent(QDragMoveEvent *event)
{
	if (event->mimeData()->hasText()) { // 修改判断条件
		event->acceptProposedAction();
	}
}

void CTableView::dragLeaveEvent(QDragLeaveEvent *event)
{
	Q_UNUSED(event);
}

void CTableView::slotItemPressed(const QModelIndex &index)
{
	if (!index.isValid())
	{
		return;
	}
	QStandardItem* item = m_model->item(index.row(), index.column());
	QPixmap* pixmap = new QPixmap(this->horizontalHeader()->sectionSize(0), this->verticalHeader()->sectionSize(0)); // 创建画布
	pixmap->fill(QColor(187, 203, 233)); // 填充绿色背景
	QPainter t_painter(this); // 创建 QPainter 对象
	t_painter.begin(pixmap);
	t_painter.drawText(QRectF(0, 0, 100, 20), Qt::AlignCenter, item->text()); // 在画布上绘制文字
	t_painter.end();
	QMimeData* t_mimeData = new QMimeData;
	t_mimeData->setText(item->text());
	QPoint hotSpot(pixmap->width() / 2, pixmap->height() / 2); // 设置热点位置为图片中心
	QDrag* t_drag = new QDrag(this);
	t_drag->setMimeData(t_mimeData);
	t_drag->setPixmap(*pixmap);
	t_drag->setHotSpot(hotSpot); // 设置热点位置
	t_drag->exec(Qt::CopyAction | Qt::MoveAction);
	delete t_drag;
	t_drag = nullptr;
	delete pixmap;
	pixmap = nullptr;
}

程序主窗口,new CTableView表格

cpp 复制代码
#include "ctestdragitem.h"
#include <QGridLayout>
const int TableCount = 9;
CTestDragItem::CTestDragItem(QWidget *parent)
	: QWidget(parent)
{
	ui.setupUi(this);
	QGridLayout* gridLayout = new QGridLayout(ui.widget);
	gridLayout->setSpacing(10);
	gridLayout->setContentsMargins(10, 10, 10, 10);

	for (int i=0; i< TableCount; i++)
	{
		CTableView * tableView = new CTableView(ui.widget);
		tableView->setHorizontalHeaderName(QString("table%1").arg(i));
		tableView->insertNewItem(QString("item%1%2").arg(i / 3).arg(i % 3));
		gridLayout->addWidget(tableView, i / 3, i % 3);
	}

}

通过以上方法就可以实现,表格数据的相互拖拽,这里只是举例了简单的用法,更复杂的操作也差不多,需要自己处理逻辑。

相关推荐
Scott9999HH8 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
码智社9 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海9 小时前
python 列表、元组、集合和字典
开发语言·python
萧瑟余晖10 小时前
JDK 26 新特性详解
java·开发语言
马优晨10 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
人邮异步社区12 小时前
怎么把C语言学到精通?
c语言·开发语言
心平气和量大福大13 小时前
C#-WPF-控件-TextBox 数据绑定
开发语言·c#·wpf
ttwuai13 小时前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang
এ慕ོ冬℘゜13 小时前
前端基础:什么是时间戳?JS获取时间戳三种方法与实战用途
开发语言·前端·javascript
执明wa13 小时前
LayoutInflater详解: XML是如何变成View的?
android·xml·开发语言·android studio