QTreeView - 如何判断拖放事件是重新排序还是父母之间的移动?

Posted

技术标签:

【中文标题】QTreeView - 如何判断拖放事件是重新排序还是父母之间的移动?【英文标题】:QTreeView - how to tell if a drag/drop event is a reorder or a move between parents? 【发布时间】:2016-11-08 20:50:19 【问题描述】:

我有QTreeViewQAbstractItemModel 的子类,目前我正在使用拖放将项目从一个父索引移动到另一个。我还想添加重新排列同一父索引中项目顺序的功能。当用户将一个项目放置在其他两个项目之间时,我需要确定应该放置在其中还是在它们之间。我还想在鼠标移动时在这两个项目之间画一条黑线,以提示将发生什么,类似于附图中的许多其他树型视图(例如大多数操作系统上的文件浏览器):

拖入现有项目:

在两个现有项目之间插入:

Qt 是否自动执行这部分拖放行为,还是我必须手动计算鼠标相对于树项边缘的位置?另外,如何在QTreeView 中的两个项目之间画一条临时线?

【问题讨论】:

【参考方案1】:

前段时间我做了几乎同样的事情,我能想到 3 件事:

你将不得不重新实现你的dropEvent(),也许你的dragMoveEvent(); 要检查物品的放置位置,请使用dropIndicatorPosition(); 要显示下降指示器,请使用setDropIndicatorShown(bool)。

这是我正在做的一个非常简单的例子。

dragMoveEvent() 中,我显示了下降指示器。这样,当您拖动对象时,您将始终显示放置指示器。

void MyTreeView::dragMoveEvent(QDragMoveEvent* event)

    setDropIndicatorShown(true);
    QTreeView::dragMoveEvent(event);

dropEvent() 中,我正在管理每个案例,也就是说,我拖动的项目是在另一个项目上、在它上面、在它下面还是在视口上。然后,据它说,我正在管理自己的掉落,并且在活动结束时,我隐藏了掉落指示器。

void MyTreeView::dropEvent(QDropEvent* event)

    bool dropOK = false;
    DropIndicatorPosition dropIndicator = dropIndicatorPosition();

    switch (dropIndicator)
    
    case QAbstractItemView::AboveItem:
        dropOK = true;
        break;
    case QAbstractItemView::BelowItem:
        dropOK = true;
        break;
    case QAbstractItemView::OnItem:
        dropOK = false;
        break;
    case QAbstractItemView::OnViewport:
        dropOK = false;
        break;
    
    if(dropOK)
    
        // Here, you need to manage yourself the case of dropping an item
    
    setDropIndicatorShown(false); // hide the drop indicator once the drop is done


“Bonus”:您可以通过PrimitiveElementPE_IndicatorItemViewItemDrop 以您自己的风格访问掉落指示器。 您可以查看如何自定义它here 和here。

【讨论】:

以上是关于QTreeView - 如何判断拖放事件是重新排序还是父母之间的移动?的主要内容,如果未能解决你的问题,请参考以下文章

在 PyQt 中支持拖放的 QTreeView

在QTreeView中拖放,removeRows没有被调用

如何根据作为输入的列表正确排序 QTreeView 中的列

拖放后的jQuery UI Sortable停止事件

QML:如何通过拖放重新排序中继器项目?里面有一些工作代码

使用 javascript 进行 HTML5 拖放 DOM 操作