Qt中自定义QTreeWidget实现节点拖拽复制功能[通俗易懂]
大家好,又见面了,我是你们的朋友全栈君。
QT中在QWidget支持拖拽功能,QTreeWidget继承自QWidget,所以自然也具有节点的拖拽功能。
拖拽包含两个功能:一个是拖动(Drag),一个是放下(Drop)。拖动的数据是QMimeData数据,MIME数据定义格式:类型/数据 (注意中间有斜线)。
若被拖动的对象放下的控件,不接受拖动的对象,Qt光标显示禁用的形状(一个禁用形状)。
开始拖动:通过调用QDrag::exec()函数启动,该函数是一个阻塞函数(但不会阻塞主事件循环),这意味着在拖放操作结束之前,不会返回该函数;通过调用setAcceptDrops()函数可设置控件是否接受放下事件。 QDragEnterEvent:拖动进入事件 QDragMoveEvnet:拖动移动事件 QDropEvent:放下事件 QDragLeaveEvent:当拖放操作离开控件时发送该事件
下面是一个实例,在树形控件中,拖动节点,并且被拖动的内容放大显示:
拖动的TreeWidget:
#pragma once
#include <QTreeWidget>
class QMouseEvent;
class QTreeWidgetItem;
class DragTreeWidget : public QTreeWidget {
Q_OBJECT
public:
DragTreeWidget(QWidget *parent);
~DragTreeWidget();
private:
void init();
private:
virtual void mousePressEvent(QMouseEvent *event)override;
private:
QTreeWidgetItem* _selectItem = nullptr;
};
#include "DragTreeWidget.h"
#include <QMouseEvent>
#include <QTreeWidgetItem>
#include <QByteArray>
#include <QDataStream>
#include <QMimeData>
#include <QDrag>
#include "QtGuiDrag.h"
DragTreeWidget::DragTreeWidget(QWidget *parent)
: QTreeWidget(parent) {
init();
setDragDropMode(QAbstractItemView::InternalMove);
setDragEnabled(true);
DragTreeWidget::~DragTreeWidget() {
void DragTreeWidget::init() {
QTreeWidgetItem* topItem = new QTreeWidgetItem(this);
topItem->setText(0, QStringLiteral("阳光小区"));
QTreeWidgetItem* item1 = new QTreeWidgetItem(topItem);
item1->setText(0, QStringLiteral("王天天"));
QTreeWidgetItem* item2 = new QTreeWidgetItem(topItem);
item2->setText(0, QStringLiteral("刘一一"));
topItem->setExpanded(true);
QTreeWidgetItem* topItem2 = new QTreeWidgetItem(this);
topItem2->setText(0, QStringLiteral("幸福小区"));
QTreeWidgetItem* item3 = new QTreeWidgetItem(topItem2);
item3->setText(0, QStringLiteral("赵鑫"));
QTreeWidgetItem* item4 = new QTreeWidgetItem(topItem2);
item4->setText(0, QStringLiteral("王旭"));
topItem2->setExpanded(true);
void DragTreeWidget::mousePressEvent(QMouseEvent *event) {
if (event->button()&Qt::LeftButton){
_selectItem = itemAt(event->pos());
QByteArray dataItem;
QDataStream dataStream(&dataItem, QIODevice::WriteOnly);
dataStream << _selectItem->text(0);
QMimeData* mimeData = new QMimeData;
mimeData->setData("Data/name", dataItem);
QtGuiDrag* dragPiamap = new QtGuiDrag(nullptr);
dragPiamap->setShowText(_selectItem->text(0));
QPixmap pixmap = dragPiamap->grab();
QDrag* drag = new QDrag(this);
drag->setPixmap(pixmap);
drag->setMimeData(mimeData);
drag->setHotSpot(QPoint(pixmap.width() / 2, pixmap.height() / 2));
drag->exec(Qt::MoveAction);
QTreeWidget::mousePressEvent(event);
}
放下的TreeWidget
#pragma once
#include <QTreeWidget>
class DropTreeWidget : public QTreeWidget {
Q_OBJECT
public:
DropTreeWidget(QWidget *parent);
~DropTreeWidget();
void dragEnterEvent(QDragEnterEvent *event)override;
void dropEvent(QDropEvent *event)override;
private:
void init();
};
#include "DropTreeWidget.h"
#include <QTreeWidgetItem>
#include <QDragEnterEvent>
#include <QDropEvent>
#include <QMimeData>
DropTreeWidget::DropTreeWidget(QWidget *parent)
: QTreeWidget(parent) {
init();
DropTreeWidget::~DropTreeWidget() {
void DropTreeWidget::dragEnterEvent(QDragEnterEvent *event) {
if (event->mimeData()->hasFormat("Data/name")){
if (event->source() == this){
event->setDropAction(Qt::MoveAction);
event->accept();
} else {
event->acceptProposedAction();
} else {
event->ignore();
void DropTreeWidget::dropEvent(QDropEvent *event) {
if (event->mimeData()->hasFormat("Data/name")) {
//获取拖拽时设置的数据
QByteArray itemData = event->mimeData()->data("Data/name");
QDataStream dataStream(&itemData, QIODevice::ReadOnly);
QString text;
dataStream >>text;
QTreeWidgetItem *item = itemAt(event->pos()); //当前位置的item
if (item == nullptr) {
return;
QTreeWidgetItem* newItem = new QTreeWidgetItem(item);
newItem->setText(0, text);
item->setExpanded(true);
if (event->source() == this) {
event->setDropAction(Qt::MoveAction);
event->accept();
} else {
event->acceptProposedAction();
} else {
event->ignore();
void DropTreeWidget::init() {
setDragDropMode(QAbstractItemView::InternalMove);
QTreeWidgetItem* topItem = new QTreeWidgetItem(this);
topItem->setText(0, QStringLiteral("一班"));
QTreeWidgetItem* topItem1 = new QTreeWidgetItem(this);
topItem1->setText(0, QStringLiteral("二班"));
}
拖动时显示的图片界面:
#pragma once
#include <QWidget>
#include "ui_QtGuiDrag.h"
//拖动时的图片显示
class QtGuiDrag : public QWidget {
Q_OBJECT
public:
QtGuiDrag(QWidget *parent = Q_NULLPTR);
~QtGuiDrag();
void setShowText(QString text);
private:
Ui::QtGuiDrag ui;
};
#include "QtGuiDrag.h"
QtGuiDrag::QtGuiDrag(QWidget *parent)
: QWidget(parent) {
ui.setupUi(this);
this->setWindowFlags(Qt::FramelessWindowHint);
this->setAttribute(Qt::WA_TranslucentBackground, true);
QtGuiDrag::~QtGuiDrag() {