Qt之 QTreeWidget:1 拖拽项目
QTreeWidget 的拖拽实现,比较简单,但过程是绕了点路的,按照常规的方法:子类化QTreeWidget、重写 Drag 和 Drop的相关事件、利用QMimeData,QDrag类来实现,功能虽然实现了,但是关闭程序是,有可能会出现异常,类似 指针被二次析构了一样。偶发性的错误,挺让我头疼。
牢骚过后,上干货。
一、官档
【 Model/View Programming 】主题中有这么一段,并试着翻译成中文,便于理解。
在便捷类中使用 拖放 功能
QListWidget、QTableWidget和QTreeWidget 中 项目 默认配置了一组不同的标志。例如,每个QListWidgetItem或QTreeWidgetItem最初都是 enabled 启用的、checkable 可检查的、selectable可选择的,并且可以用作拖放源;每个QTableWidgetItem也可以编辑并用作拖放操作的目标。
通常需要在视图本身中设置相关属性启动对拖放的内置支持:
- 设置dragEnabled属性为true,启用项拖动功能
- 设置 viewport() 的acceptDrops属性设置为true,允许用户在视图中放置内部或外部的项
- 设置视图的showDropIndicator属性,向用户显示当前正在拖动的项以及放置的位置。
- 设置视图的 dragDropMode(QAbstractItemView::InternalMove),在视图中移动项目,
二、测试
上述内容还是比较容易理解的,那就看看实际效果呗。
#include <QtWidgets>
#include "../../DebugTools/DebugTool.h"
void init(QTreeWidget &w){
w.setHeaderLabels ({"节点","内容"});
QList<QTreeWidgetItem *> list;
// 3 行 2列,每行2个子节点
for (int i = 0; i < 3; ++i) {
QTreeWidgetItem *item = new QTreeWidgetItem(&w);
item->setFlags (Qt::ItemIsEditable | item->flags ());
cout << item->flags ();
item->setExpanded (true); // 只有设置了父控件,才能展开
list << item;
item->setText (0,QString("父节点%1").arg (i));
item->setText (1,item->text (0));
for (int j = 0; j < 2; ++j) {
QTreeWidgetItem *child = new QTreeWidgetItem(item);
child->setFlags (Qt::ItemIsEditable | item->flags ());
child->setText (0,QString("子节点%1-%2").arg (i).arg(j));
child->setText (1,child->text (0));
}
}
w.addTopLevelItems (list);
w.resize (300,300);
w.resizeColumnToContents (1);
w.header ()->setSectionsClickable (false);
w.setEditTriggers (QTreeWidget::DoubleClicked );
}
void setDragAndDrop(QTreeWidget &w){
w.setDragEnabled (true); // 启用拖动
w.viewport ()->setAcceptDrops (true); // viewport 接受放下动作,默认是复制操作
w.showDropIndicator (); // 设置放下指示
w.setDragDropMode (QTreeWidget::InternalMove);// 内部 移动
}
void setSelectionMode(QTreeWidget &w){
w.setSelectionBehavior (QTreeWidget::SelectRows); // 选择行
w.setSelectionMode (QTreeWidget::ContiguousSelection);// 连续选择
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTreeWidget w;
// 初始化Tree
init (w);
// 设置Tree的拖放
setDragAndDrop(w);
// 设置Tree的选定模式和行为
setSelectionMode (w);
w.show ();
return a.exec();
}