qt中用treewidget创建横向表格,实现两个treewidget能相互拖动item,并且只能拖动到到根节点的子节点同级节点
时间: 2024-02-01 10:13:26 浏览: 158
实现这个功能需要以下几个步骤:
1. 创建两个QTreeWidget,一个作为源,一个作为目标。
2. 设置源QTreeWidget为可拖动,目标QTreeWidget为可接受拖放。
```cpp
sourceWidget->setDragEnabled(true);
targetWidget->setAcceptDrops(true);
```
3. 在源QTreeWidget的mousePressEvent事件中,记录被拖动的item和它的父节点。
```cpp
if (event->button() == Qt::LeftButton) {
QTreeWidgetItem *item = sourceWidget->itemAt(event->pos());
if (item && item->parent()) {
m_draggedItem = item;
m_draggedParent = item->parent();
}
}
```
4. 在源QTreeWidget的mouseMoveEvent事件中,如果鼠标移动的距离大于一定阈值,就开始拖拽操作。
```cpp
if (m_draggedItem && (event->buttons() & Qt::LeftButton)) {
int distance = (event->pos() - m_pressPos).manhattanLength();
if (distance >= QApplication::startDragDistance()) {
QDrag *drag = new QDrag(this);
QMimeData *mimeData = new QMimeData;
mimeData->setData("application/x-qabstractitemmodeldatalist",
sourceWidget->model()->itemData(m_draggedItem).value<QByteArray>());
drag->setMimeData(mimeData);
drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction);
}
}
```
5. 在目标QTreeWidget的dragEnterEvent和dragMoveEvent事件中,检查被拖动的item是否可以拖放到指定位置。如果不能,就设置禁止拖放的光标。
```cpp
if (event->mimeData()->hasFormat("application/x-qabstractitemmodeldatalist")) {
QTreeWidgetItem *targetItem = this->itemAt(event->pos());
QTreeWidgetItem *parentItem = targetItem ? targetItem->parent() : this->invisibleRootItem();
if (parentItem == m_draggedParent) {
event->accept();
} else {
event->ignore();
this->setCursor(Qt::ForbiddenCursor);
}
} else {
event->ignore();
}
```
6. 在目标QTreeWidget的dropEvent事件中,将被拖动的item插入到指定位置。
```cpp
if (event->mimeData()->hasFormat("application/x-qabstractitemmodeldatalist")) {
QByteArray data = event->mimeData()->data("application/x-qabstractitemmodeldatalist");
QDataStream stream(&data, QIODevice::ReadOnly);
QList<QVariant> itemData;
QPoint offset;
stream >> itemData >> offset;
QTreeWidgetItem *targetItem = this->itemAt(event->pos());
QTreeWidgetItem *parentItem = targetItem ? targetItem->parent() : this->invisibleRootItem();
if (parentItem == m_draggedParent) {
QTreeWidgetItem *newItem = new QTreeWidgetItem(parentItem, itemData);
parentItem->insertChild(targetItem ? this->indexOfTopLevelItem(targetItem) : parentItem->childCount(), newItem);
event->accept();
} else {
event->ignore();
}
}
```
完整的代码示例:
```cpp
#include <QtWidgets>
class TreeWidget : public QWidget {
public:
TreeWidget(QWidget *parent = nullptr) : QWidget(parent) {
QVBoxLayout *layout = new QVBoxLayout(this);
QHBoxLayout *hlayout = new QHBoxLayout;
layout->addLayout(hlayout);
m_sourceWidget = new QTreeWidget(this);
m_sourceWidget->setColumnCount(1);
m_sourceWidget->setHeaderHidden(true);
m_sourceWidget->setDragEnabled(true);
hlayout->addWidget(m_sourceWidget);
m_targetWidget = new QTreeWidget(this);
m_targetWidget->setColumnCount(1);
m_targetWidget->setHeaderHidden(true);
m_targetWidget->setAcceptDrops(true);
hlayout->addWidget(m_targetWidget);
QTreeWidgetItem *rootItem = new QTreeWidgetItem(m_sourceWidget, {"Root"});
QTreeWidgetItem *childItem = new QTreeWidgetItem(rootItem, {"Child"});
rootItem->addChild(childItem);
connect(m_sourceWidget, &QTreeWidget::itemPressed, this, &TreeWidget::onSourceItemPressed);
connect(m_targetWidget, &QTreeWidget::dragEnterEvent, this, &TreeWidget::onTargetDragEnter);
connect(m_targetWidget, &QTreeWidget::dragMoveEvent, this, &TreeWidget::onTargetDragMove);
connect(m_targetWidget, &QTreeWidget::dropEvent, this, &TreeWidget::onTargetDrop);
}
void onSourceItemPressed(QTreeWidgetItem *item, int column) {
Q_UNUSED(column)
m_draggedItem = nullptr;
m_draggedParent = nullptr;
m_pressPos = QCursor::pos();
if (item && item->parent()) {
m_draggedItem = item;
m_draggedParent = item->parent();
}
}
void onTargetDragEnter(QDragEnterEvent *event) {
if (event->mimeData()->hasFormat("application/x-qabstractitemmodeldatalist")) {
QTreeWidgetItem *targetItem = m_targetWidget->itemAt(event->pos());
QTreeWidgetItem *parentItem = targetItem ? targetItem->parent() : m_targetWidget->invisibleRootItem();
if (parentItem == m_draggedParent) {
event->accept();
} else {
event->ignore();
m_targetWidget->setCursor(Qt::ForbiddenCursor);
}
} else {
event->ignore();
}
}
void onTargetDragMove(QDragMoveEvent *event) {
if (event->mimeData()->hasFormat("application/x-qabstractitemmodeldatalist")) {
QTreeWidgetItem *targetItem = m_targetWidget->itemAt(event->pos());
QTreeWidgetItem *parentItem = targetItem ? targetItem->parent() : m_targetWidget->invisibleRootItem();
if (parentItem == m_draggedParent) {
event->accept();
} else {
event->ignore();
m_targetWidget->setCursor(Qt::ForbiddenCursor);
}
} else {
event->ignore();
}
}
void onTargetDrop(QDropEvent *event) {
if (event->mimeData()->hasFormat("application/x-qabstractitemmodeldatalist")) {
QByteArray data = event->mimeData()->data("application/x-qabstractitemmodeldatalist");
QDataStream stream(&data, QIODevice::ReadOnly);
QList<QVariant> itemData;
QPoint offset;
stream >> itemData >> offset;
QTreeWidgetItem *targetItem = m_targetWidget->itemAt(event->pos());
QTreeWidgetItem *parentItem = targetItem ? targetItem->parent() : m_targetWidget->invisibleRootItem();
if (parentItem == m_draggedParent) {
QTreeWidgetItem *newItem = new QTreeWidgetItem(parentItem, itemData);
parentItem->insertChild(targetItem ? m_targetWidget->indexOfTopLevelItem(targetItem) : parentItem->childCount(), newItem);
event->accept();
} else {
event->ignore();
}
} else {
event->ignore();
}
}
private:
QTreeWidget *m_sourceWidget;
QTreeWidget *m_targetWidget;
QTreeWidgetItem *m_draggedItem;
QTreeWidgetItem *m_draggedParent;
QPoint m_pressPos;
};
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
TreeWidget widget;
widget.show();
return app.exec();
}
```
阅读全文