【QT】QTreeWidget实现拖拽Item


前言

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);
}
  • 5
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
实现QTreeWidget之间的拖拽功能,需要进行以下步骤: 1.在源QTreeWidget中启用拖拽功能:调用setDragEnabled(True)方法来启用拖拽功能。 2.实现startDrag方法:当用户开始拖拽一个项目时,调用startDrag方法。该方法创建QDrag对象并将要拖动的数据存储在其中。 3.在目标QTreeWidget中启用放置功能:调用setAcceptDrops(True)方法来启用放置功能。 4.实现dragEnterEvent方法:当用户将拖动的项目拖到目标QTreeWidget上时,调用dragEnterEvent方法。该方法检查拖动的数据是否与目标兼容,并在兼容的情况下接受拖放操作。 5.实现dropEvent方法:当用户在目标QTreeWidget上放置拖动的项目时,调用dropEvent方法。该方法将项目添加到目标QTreeWidget中。 下面是一个示例代码: ```python class TreeWidget(QTreeWidget): def __init__(self, parent=None): super(TreeWidget, self).__init__(parent) self.setAcceptDrops(True) self.setDragEnabled(True) def startDrag(self, event): item = self.currentItem() if item: data = QByteArray() stream = QDataStream(data, QIODevice.WriteOnly) stream.writeQString(item.text(0)) mimeData = QMimeData() mimeData.setData('application/x-qabstractitemmodeldatalist', data) drag = QDrag(self) drag.setMimeData(mimeData) drag.exec_() def dragEnterEvent(self, event): if event.mimeData().hasFormat('application/x-qabstractitemmodeldatalist'): event.accept() else: event.ignore() def dropEvent(self, event): if event.mimeData().hasFormat('application/x-qabstractitemmodeldatalist'): data = event.mimeData().data('application/x-qabstractitemmodeldatalist') stream = QDataStream(data, QIODevice.ReadOnly) text = '' stream >> text item = QTreeWidgetItem(self) item.setText(0, text) event.accept() else: event.ignore() ``` 在上面的代码中,我们继承了QTreeWidget类,并重写了startDrag,dragEnterEvent和dropEvent方法。startDrag方法创建了一个QMimeData对象并存储要拖动的数据。dragEnterEvent方法检查拖动的数据是否与目标兼容,并在兼容的情况下接受拖放操作。dropEvent方法将项目添加到目标QTreeWidget中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值