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

}

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

相关推荐
用户805533698034 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner4 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz9 天前
QML Hello World 入门示例
qt
xcyxiner12 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner13 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner13 天前
DicomViewer (添加模型类)3
qt
xcyxiner14 天前
DicomViewer (目录调整) 2
qt
xcyxiner14 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
LDR00616 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术16 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript