前言
QTreeWidget实现拖拽,顶层item拖拽到顶层item时,在当前顶层item前面进行插入,顶层item拖拽到非顶层item上禁止,非顶层item拖拽到顶层item上,当前顶层item添加拖拽的非顶层item,非顶层item拖拽到非顶层item上,当前非顶层item前面插入拖拽的非顶层item。
提示:以下是本篇文章正文内容,下面案例可供参考
1.效果展示
拖拽
2.fbasetreewidget.h
代码如下(示例):
#ifndef FBASETREEWIDGET_H
#define FBASETREEWIDGET_H
#include <QTreeWidget>
#include <QMimeData>
#include <QLabel>
#include <QVector>
#include <QMouseEvent>
#include <QDragEnterEvent>
class FBaseTreeWidget : public QTreeWidget
{
Q_OBJECT
public:
FBaseTreeWidget(QWidget *parent = 0);
~FBaseTreeWidget();
protected:
//需要重新实现的事件
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void dragEnterEvent(QDragEnterEvent * event);
void dropEvent(QDropEvent *event);
void dragMoveEvent(QDragMoveEvent *event);
private:
QRect m_rect;
QTreeWidgetItem * curItem;
QPoint startDragPoint;
};
#endif // FBASETREEWIDGET_H
3.treeitemmimedata.cpp
代码如下(示例):
#include "fbasetreewidget.h"
#include <QDebug>
#include <QKeyEvent>
#include <QMouseEvent>
#include <QApplication>
#include <QDrag>
#include "treeitemmimedata.h"
FBaseTreeWidget::FBaseTreeWidget(QWidget *parent) :
QTreeWidget(parent)
{
this->setSelectionMode(QAbstractItemView::SingleSelection);
this->setDragEnabled(true);
this->setAcceptDrops(true);
this->viewport()->setAcceptDrops(true);
this->setDragDropMode(QAbstractItemView::InternalMove);
connect(this, &FBaseTreeWidget::itemClicked, this, [=](){qDebug()<< this->currentItem()->text(0);});
}
FBaseTreeWidget::~FBaseTreeWidget()
{
}
void FBaseTreeWidget::mousePressEvent(QMouseEvent *event)
{
if( event->button() == Qt::LeftButton ){
startDragPoint = event->pos();
curItem = this->itemAt(event->pos());
m_rect = visualRect(indexAt(startDragPoint));
}
QTreeWidget::mousePressEvent(event);
}
void FBaseTreeWidget::mouseMoveEvent(QMouseEvent *event)
{
if( event->buttons() & Qt::LeftButton){
int distance = (event->pos()-startDragPoint ).manhattanLength();
if( distance > QApplication::startDragDistance()){
TreeItemMimeData *mimedata = new TreeItemMimeData;
mimedata->SetDragData("ItemMimeData",curItem);
QDrag *drag = new QDrag(this);
drag->setMimeData(mimedata);
QPixmap pixmap = this->grab(m_rect);
if (!pixmap.isNull()){
drag->setPixmap(pixmap);
drag->setHotSpot(QPoint(0, pixmap.height()/2));
}
drag->setHotSpot(QPoint(pixmap.width() / 2, pixmap.height() / 2));
if( drag->exec(Qt::MoveAction) == Qt::MoveAction){
delete curItem;
curItem = nullptr;
}
}
}
QTreeWidget::mouseMoveEvent(event);
}
void FBaseTreeWidget::dragEnterEvent(QDragEnterEvent *event)
{
if (event->mimeData()->hasFormat("ItemMimeData") && event->source() == this ){
event->setDropAction(Qt::MoveAction);
event->accept();
}
else
event->ignore();
}
void FBaseTreeWidget::dropEvent(QDropEvent *event)
{
if(event->mimeData()->hasFormat("ItemMimeData") && event->source() == this ){
const TreeItemMimeData *pMimeData = (const TreeItemMimeData *)(event->mimeData());
const QTreeWidgetItem *item = pMimeData->DragItemData();
if(item == nullptr)
return;
QTreeWidgetItem *pItem = item->clone();
QTreeWidgetItem *currentItem = this->itemAt(event->pos());
if(currentItem == nullptr)
return;
else{
QTreeWidgetItem * currenParent = currentItem->parent();
if(currenParent == nullptr){
if(item->parent() == nullptr)
insertTopLevelItem(indexOfTopLevelItem(currentItem),pItem);
else
currentItem->addChild(pItem);
}
else{
if(item->parent() == nullptr)
return;
else
currenParent->insertChild(currenParent->indexOfChild(currentItem),pItem);
}
}
if(pItem->childCount() != 0)
pItem->setExpanded(true);
this->setCurrentItem(pItem);
event->setDropAction(Qt::MoveAction);
event->accept();
}
else
event->ignore();
}
void FBaseTreeWidget::dragMoveEvent(QDragMoveEvent *event)
{
if (event->mimeData()->hasFormat("ItemMimeData") && event->source() == this ){
const TreeItemMimeData *pMimeData = (const TreeItemMimeData *)(event->mimeData());
const QTreeWidgetItem *item = pMimeData->DragItemData();
QTreeWidgetItem *currentItem = this->itemAt(event->pos());
bool isok = true;
while(currentItem){
if(currentItem == item){
isok = false;
break;
}
currentItem = currentItem->parent();
}
if( isok ){
event->setDropAction(Qt::CopyAction);
event->accept();
}
else
event->ignore();
}
else
event->ignore();
}
4.treeitemmimedata.h
#ifndef TREEITEMMIMEDATA_H
#define TREEITEMMIMEDATA_H
#include <QMimeData>
class QTreeWidgetItem;
class TreeItemMimeData : public QMimeData
{
Q_OBJECT
public:
TreeItemMimeData():QMimeData(){}
QStringList formats() const {return m_format ;}
const QTreeWidgetItem * DragItemData() const { return m_pDragItem;}
void SetDragData(QString mimeType,QTreeWidgetItem * pItem);
private:
QStringList m_format;
const QTreeWidgetItem * m_pDragItem;
protected:
QVariant retrieveData(const QString &mimetype, QVariant::Type preferredType) const ;
};
#endif // TREEITEMMIMEDATA_H
4.treeitemmimedata.cpp
#include "treeitemmimedata.h"
void TreeItemMimeData::SetDragData(QString mimeType, QTreeWidgetItem *pItem)
{
m_format << mimeType;
m_pDragItem = pItem;
}
QVariant TreeItemMimeData::retrieveData(const QString &mimetype, QVariant::Type preferredType) const
{
if( mimetype == "ItemMimeData")
{
return m_pDragItem;
}
else
return QMimeData::retrieveData(mimetype,preferredType);
}