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

}

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

相关推荐
流星白龙15 分钟前
【C++习题】10.反转字符串中的单词 lll
开发语言·c++
尘浮生22 分钟前
Java项目实战II基于微信小程序的校运会管理系统(开发文档+数据库+源码)
java·开发语言·数据库·微信小程序·小程序·maven·intellij-idea
MessiGo23 分钟前
Python 爬虫 (1)基础 | 基础操作
开发语言·python
Tech Synapse28 分钟前
Java根据前端返回的字段名进行查询数据的方法
java·开发语言·后端
乌啼霜满天24937 分钟前
JDBC编程---Java
java·开发语言·sql
色空大师1 小时前
23种设计模式
java·开发语言·设计模式
Bruce小鬼1 小时前
QT文件基本操作
开发语言·qt
2202_754421541 小时前
生成MPSOC以及ZYNQ的启动文件BOOT.BIN的小软件
java·linux·开发语言
我只会发热1 小时前
Java SE 与 Java EE:基础与进阶的探索之旅
java·开发语言·java-ee
懷淰メ1 小时前
PyQt飞机大战游戏(附下载地址)
开发语言·python·qt·游戏·pyqt·游戏开发·pyqt5