Qt之 QTreeWidget:1 拖拽项目

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();
}
  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要实现QTreeWidget之间的拖拽功能,需要进行以下步骤: 1.在源QTreeWidget中启用拖拽功能:调用setDragEnabled(True)方法来启用拖拽功能。 2.实现startDrag方法:当用户开始拖拽一个项目时,调用startDrag方法。该方法创建QDrag对象并将要拖动的数据存储在其中。 3.在目标QTreeWidget中启用放置功能:调用setAcceptDrops(True)方法来启用放置功能。 4.实现dragEnterEvent方法:当用户将拖动的项目拖到目标QTreeWidget上时,调用dragEnterEvent方法。该方法检查拖动的数据是否与目标兼容,并在兼容的情况下接受拖放操作。 5.实现dropEvent方法:当用户在目标QTreeWidget上放置拖动的项目时,调用dropEvent方法。该方法将项目添加到目标QTreeWidget中。 下面是一个示例代码: ```python class TreeWidget(QTreeWidget): def __init__(self, parent=None): super(TreeWidget, self).__init__(parent) self.setAcceptDrops(True) self.setDragEnabled(True) def startDrag(self, event): item = self.currentItem() if item: data = QByteArray() stream = QDataStream(data, QIODevice.WriteOnly) stream.writeQString(item.text(0)) mimeData = QMimeData() mimeData.setData('application/x-qabstractitemmodeldatalist', data) drag = QDrag(self) drag.setMimeData(mimeData) drag.exec_() def dragEnterEvent(self, event): if event.mimeData().hasFormat('application/x-qabstractitemmodeldatalist'): event.accept() else: event.ignore() def dropEvent(self, event): if event.mimeData().hasFormat('application/x-qabstractitemmodeldatalist'): data = event.mimeData().data('application/x-qabstractitemmodeldatalist') stream = QDataStream(data, QIODevice.ReadOnly) text = '' stream >> text item = QTreeWidgetItem(self) item.setText(0, text) event.accept() else: event.ignore() ``` 在上面的代码中,我们继承了QTreeWidget类,并重写了startDrag,dragEnterEvent和dropEvent方法。startDrag方法创建了一个QMimeData对象并存储要拖动的数据。dragEnterEvent方法检查拖动的数据是否与目标兼容,并在兼容的情况下接受拖放操作。dropEvent方法将项目添加到目标QTreeWidget中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值