如何在QGraphicsScene的dropEvent中获取拖拽的QTreeWidgetItem数据
解决QTreeWidget拖拽条目到QGraphicsScene无法获取条目信息的问题
你遇到的问题是因为Qt模型视图框架的拖拽逻辑,QTreeWidget默认不会将条目文本写入MIME的text字段,而是将选中条目的所有角色数据序列化后存储在application/x-qabstractitemmodeldatalist格式的二进制数据中,所以直接读取text()和objectName()都会返回空值,以下是两种可行解决方案:
方法1:直接解析Qt默认MIME数据
不需要修改现有QTreeWidget的代码,直接在dropEvent中解析二进制数据即可,适合仅需要读取条目内置角色(如显示文本、图标等)的场景:
void Scene::dropEvent(QGraphicsSceneDragDropEvent* event) { if (event->mimeData()->hasFormat("application/x-qabstractitemmodeldatalist")) { QByteArray itemData = event->mimeData()->data("application/x-qabstractitemmodeldatalist"); QDataStream stream(&itemData, QIODevice::ReadOnly); int row, col; QMap<int, QVariant> roleDataMap; // 循环读取所有被拖拽的条目数据 while (!stream.atEnd()) { stream >> row >> col >> roleDataMap; // 示例:取第一列的显示文本,需要其他列调整col值即可 if (col == 0) { QString itemText = roleDataMap[Qt::DisplayRole].toString(); // 此处拿到文本后即可创建对应的矩形对象 qDebug() << "拖拽条目文本:" << itemText; } } } event->acceptProposedAction(); }
如果需要读取条目存储的自定义数据,只需把Qt::DisplayRole替换为你自定义的Qt::UserRole枚举值即可。
方法2:自定义拖拽MIME数据(更灵活)
如果需要传递更复杂的自定义信息,推荐重写QTreeWidget的startDrag方法,自行构造MIME数据,后续读取逻辑更简单:
- 子类化QTreeWidget,重写
startDrag虚函数:
// MyTreeWidget.h 声明 class MyTreeWidget : public QTreeWidget { Q_OBJECT protected: void startDrag(Qt::DropActions supportedActions) override; }; // MyTreeWidget.cpp 实现 void MyTreeWidget::startDrag(Qt::DropActions supportedActions) { QList<QTreeWidgetItem*> selected = selectedItems(); if (selected.isEmpty()) return; QMimeData* mime = new QMimeData(); // 直接存入你需要的条目信息 mime->setText(selected.first()->text(0)); // 如需传递自定义数据可以用自定义MIME格式存储 // mime->setData("application/x-my-custom-item", selected.first()->data(0, Qt::UserRole).toByteArray()); QDrag* drag = new QDrag(this); drag->setMimeData(mime); drag->exec(supportedActions); }
- 将原有代码中
m_nodeList的实例类型从QTreeWidget替换为MyTreeWidget,初始化配置不需要修改,之后在dropEvent中直接读取即可:
void Scene::dropEvent(QGraphicsSceneDragDropEvent* event) { if (event->mimeData()->hasText()) { QString itemText = event->mimeData()->text(); // 直接使用文本创建矩形对象即可 } event->acceptProposedAction(); }
内容的提问来源于stack exchange,提问作者Jepessen
相关产品推荐
相关产品推荐

