Qt:QTreeWidget拖拽item到QGraphicsScene

简述:
简单的实现了QTreeWidget 拖拽图形 到QGraphicsScene的演示效果。
拖拽的实现,一般需要四个函数

//鼠标压下事件,启动拖拽事件
void mousePressEvent(QMouseEvent* event) override;
//drag操作在窗体移动事件
void dragMoveEvent(QDragMoveEvent* event) override;
//drag操作进入窗体
void dragEnterEvent(QDragEnterEvent* event) override;
//drop释放事件
void dropEvent(QDropEvent* event) override;

中间有很多坑,其实是文档没看明白。
我代码简单实现自定义qtreewidget 点击 启动拖拽一个MimeData,MimeData可以添加很多类型数据,我这里拖拽一个label用于显示。拖拽到了GraphicsView 里再次传递给自定义的GraphicsScene 接收。
自定义场景类MyScene里 开启拖拽接收权限,当鼠标释放,接收传递的数据。

  #ifndef MYSCENE_H
  #define MYSCENE_H
  #include <QGraphicsScene>
#include <QGraphicsSceneEvent>
#include <QGraphicsSceneDragDropEvent>
#include <QMimeData>
#include <QGraphicsRectItem>
#include <QObject>
#include <QDrag>
class MyScene:public QGraphicsScene
    Q_OBJECT
public:
    MyScene(QObject *parent = nullptr);
protected:
    //drag操作在窗体移动事件
    void dragMoveEvent(QGraphicsSceneDragDropEvent *event) override;
    //drag操作进入窗体
    void dragEnterEvent(QGraphicsSceneDragDropEvent* event) ;
    //drop释放事件
    void dropEvent(QGraphicsSceneDragDropEvent* event) ;
#endif // MYSCENE_H
#include "MyScene.h"
#include <QDebug>
MyScene::MyScene(QObject *parent):QGraphicsScene(parent)
void MyScene::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
    //坑1 并不是在DragEnterEvent 开启接受权限 而是在这
    event->accept();
    //event->setAccepted(true);
    //不能调用父类的,会把权限关闭
  //  QGraphicsScene::dragMoveEvent(event);
void MyScene::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
    event->accept();
    //event->setAccepted(true);
    QGraphicsScene::dragEnterEvent(event);
void MyScene::dropEvent(QGraphicsSceneDragDropEvent *event)
    if (event->mimeData()->hasFormat("Data/name"))
        //获取拖拽的数据
        QByteArray itemData = event->mimeData()->data("Data/name");
        QDataStream dataStream(&itemData, QIODevice::ReadOnly);
        QString text;
        dataStream >>text;
        qDebug()<<text;
        //创建一个item
        QGraphicsRectItem  * item = new QGraphicsRectItem();
        //坑2 event->pos() 失效了 坐标一直是(0,0),直接用场景坐标
        item->setRect(event->scenePos().x(),event->scenePos().y(),100,50);
        this->addItem(item);
    QGraphicsScene::dropEvent(event);

自定义QTreeWidget 类

#include "MyScene.h"
#include <QDebug>
MyScene::MyScene(QObject *parent):QGraphicsScene(parent)
void MyScene::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
    //坑1 并不是在DragEnterEvent 开启接受权限 而是在这
    event->accept();
    //event->setAccepted(true);
    //不能调用父类的,会把权限关闭
  //  QGraphicsScene::dragMoveEvent(event);
void MyScene::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
    event->accept();
    //event->setAccepted(true);
    QGraphicsScene::dragEnterEvent(event);
void MyScene::dropEvent(QGraphicsSceneDragDropEvent *event)
    if (event->mimeData()->hasFormat("Data/name"))
        //获取拖拽的数据
        QByteArray itemData = event->mimeData()->data("Data/name");
        QDataStream dataStream(&itemData, QIODevice::ReadOnly);
        QString text;
        dataStream >>text;
        qDebug()<<text;
        //创建一个item
        QGraphicsRectItem  * item = new QGraphicsRectItem();
        //坑2 event->pos() 失效了 坐标一直是(0,0),直接用场景坐标
        item->setRect(event->scenePos().x(),event->scenePos().y(),100,50);
        this->addItem(item);
    QGraphicsScene::dropEvent(event);
#include "MyTree.h"
#include <QMimeData>
MyTree::MyTree(QWidget *parent):QTreeWidget(parent)
void MyTree::init()
    //设置树形头部控件
    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);
    m_label = new QLabel(this);
    m_label->resize(100,50);
    m_label->hide();
void MyTree::mousePressEvent(QMouseEvent *event)
    m_selectItem = static_cast<QTreeWidgetItem*>(this->itemAt(event->pos()));
    if (event->button()==Qt::LeftButton&&m_selectItem){
        QByteArray dataItem;
        QDataStream dataStream(&dataItem, QIODevice::WriteOnly);
        dataStream << m_selectItem->text(0);
        m_label->setText(m_selectItem->text(0));
        //设置自定义数据
        QMimeData* mimeData = new QMimeData;
        mimeData->setData("Data/name", dataItem);
        //拖动设置
        QDrag* drag = new QDrag(this);
        drag->setPixmap(m_label->grab());
        drag->setMimeData(mimeData);
        drag->setHotSpot(QPoint(0,0));
        drag->exec();
//       Qt::DropAction dropAction = drag->exec(Qt::MoveAction|Qt::CopyAction,Qt::CopyAction);
//        if(dropAction == Qt::MoveAction)
//        {
//            //当成功拖动时清除原节点
//            delete m_selectItem;
//            m_selectItem = NULL;
//            qDebug()<<"成功";
//        }
    QTreeWidget::mousePressEvent(event);
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include "MyTree.h"
#include "MyScene.h"
#include <QGraphicsView>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
    Q_OBJECT
public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
private:
    Ui::Widget *ui;
    MyTree  * mytree;
    MyScene * myscene;
    QGraphicsView * view;
#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"
#include <QRectF>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
    ui->setupUi(this);
    resize(500,500);
    mytree = new MyTree(this);
    mytree->setGeometry(0,0,180,500);
    mytree->init();
    myscene = new MyScene;
    myscene->setSceneRect(QRect(0,0,300,500));
    view = new  QGraphicsView(this);
    //view->setAcceptDrops(true);
    view ->setGeometry(200,0,300,500);
    view->setScene(myscene);
Widget::~Widget()