QT中QTreeWidget的拖放操作

在学习Qt的过程中接触过QListWidget和QTextWidget的拖放操作,现QT项目实操需用到树形节点拖放的操作,在参考了教程与案例后,做个实践小Demo:

class TreeWidget : public QTreeWidget
{
    Q_OBJECT

public:
    explicit TreeWidget(QWidget *parent = nullptr);    

    //创建树形
    void init();    

protected:

    //鼠标压下事件,启动拖拽事件
    void mousePressEvent(QMouseEvent* event) override;

    //drag操作在窗体移动事件
    void dragMoveEvent(QDragMoveEvent* event) override;

    //drag操作进入窗体
    void dragEnterEvent(QDragEnterEvent* event) override;

    //drop释放事件
    void dropEvent(QDropEvent* event) override;    

private:
    //拖放显示控件
    QLabel* label;  

    //选中拖动节点 
    QTreeWidgetItem* _selectItem;    
};

虽然用QTreeView也可以实现,但QTreeWidget封装好了树形视图与标准模型,使用起来更加简单方便,因此采用继承QTreeWidget重写QWidget的拖放方法的方式实现拖放功能:

在创建树形前设置拖放设定:

//设置拖放模式为内部移动

setDragDropMode(QAbstractItemView::InternalMove);    

//允许接受drop操作

setAcceptDrops(true);

创建树形:

//设置树形头部控件
setHeaderLabel(tr("节点拖动Demo"));    

//创建树形
//父节点1
QTreeWidgetItem* pTree1 = new QTreeWidgetItem(this);
pTree1->setText(0,QStringLiteral("父节点1"));

//子节点
QTreeWidgetItem* sTree1_1 = new QTreeWidgetItem(pTree1);
sTree1_1->setText(0,QStringLiteral("子节点1"));

QTreeWidgetItem* sTree1_2 = new QTreeWidgetItem(pTree1);
sTree1_2->setText(0,QStringLiteral("子节点2"));
pTree1->setExpanded(true);

重写拖放方法,其中dragEnterEvent与dragMoveEvent基本相同:

void TreeWidget::mousePressEvent(QMouseEvent *event)
{
    _selectItem= static_cast(this->itemAt(event->pos()));
    if (event->button()==Qt::LeftButton&&_selectItem){    
  	QByteArray dataItem;
        QDataStream dataStream(&dataItem, QIODevice::WriteOnly);
        dataStream << _selectItem->text(0);       
        label->setText(_selectItem->text(0));
        
        //设置自定义数据
        QMimeData* mimeData = new QMimeData;
        mimeData->setData("Data/name", dataItem);

        //拖动设置
        QDrag* drag = new QDrag(this);
        drag->setPixmap(label->grab());
        drag->setMimeData(mimeData);
        drag->setHotSpot(QPoint(label->grab().width() / 2, label->grab().height() / 2));

        Qt::DropAction dropAction = drag->exec(Qt::MoveAction|Qt::CopyAction,Qt::CopyAction);
        if(dropAction == Qt::MoveAction){
            //当成功拖动时清除原节点
            delete _selectItem;
            _selectItem = NULL;
        }
    }
    QTreeWidget::mousePressEvent(event);  
}


void TreeWidget::dragMoveEvent(QDragMoveEvent *event)
{
  //判断自定义类型
   if (event->mimeData()->hasFormat("Data/name")){
        //children()返回所有子对象,ev->sourve返回当前拖拽的对象
        if(children().contains(event->source())){
            event->setDropAction(Qt::MoveAction);
            event->accept();
        } else {
            event->acceptProposedAction();
        }
    } else {
        event->ignore();
    }
}

void TreeWidget::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());     
        if (item == nullptr) { 
            return;
        }else if(item == _selectItem){
             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();
    }
}

至此demo完成,这里没有对父节点的拖放进行控制,
但QTreeWidget::setFlags(Qt::ItemFlags)可对节点属性进行更多设置。
看下实际效果:
QT中QTreeWidget的拖放操作_第1张图片

你可能感兴趣的:(知识点练习)