【问题标题】:Drag and drop in QTreeView, removeRows not called在QTreeView中拖放,removeRows没有被调用
【发布时间】:2014-06-16 19:18:49
【问题描述】:

我在QTreeView中的拖放有一些问题:

我将标志设置为Qt::MoveAction 并在我的模型中重新实现removeRows()dropMimeData() 等。模型继承QAbstractItemModel

当我拖放时,mimeData()dropMimeData() 会被自动调用, 还有dropMimeData() 自动调用insertRows()。但是removeRows()没有被调用,所以被拖拽的item还活着。我用谷歌搜索,但他们说他们的removeRows() 是自动调用的。

  • 为什么我的removeRows() 不在dropMimeData() 之后调用?
  • 我应该在dropMimeData() 中手动调用removeRows() 吗?
  • 如果是这样,我怎么知道前一个拖动开始的QModelIndex

当开始拖动时,在mimeData(),我可以将索引保存在私有成员中,但看起来不太好。

任何建议将不胜感激。

【问题讨论】:

    标签: qt drag-and-drop treeview


    【解决方案1】:

    简答

    如果一切配置正确,则目标不应移除源项,如果执行Qt::MoveAction,则拖动的发起者应移除源项。

    视图配置

    QAbstractItemView(是QTreeViewQListViewQTableView、...的基类)实现QDrag操作在startDrag中的发起和结束:

    if (drag->exec(supportedActions, defaultDropAction) == Qt::MoveAction)
        d->clearOrRemove();
    

    因此,当请求的删除操作(由QDrag::exec 返回)是Qt::MoveAction 时,该项目将自动删除(或由setDragDropOverwriteMode 指定清除)。

    视图的重要配置选项有:

    模型配置

    除了视图的配置,你应该正确配置你的模型。

    • 您应该实现模型的编辑界面,即removeRowsinsertRowsmoveRowssetData。尽管根据您的具体情况可能没有必要实现所有这些,但对于可编辑模型来说,无论如何实现它们都是一种好方法。

    • supportedDropActions:重新实现此函数以返回支持删除操作(默认为Qt::CopyAction)。请注意,用户可以通过按一些键在不同的支持操作之间切换。 (shift 代表 Qt::MoveActioncontrol 代表 Qt::CopyAction

      • supportedDragActions:如果支持的拖动操作与支持的拖放操作不同,请重新实现此功能。

    示例

    很好的例子是 Qt 本身的源代码。对应的Q*Widget 类(例如QTreeWidget 用于QTreeView)提供了视图和对应模型的具体实现。

    【讨论】:

    • 我遇到的另一件事:视图的selectionBehavior 必须设置为QAbstractItemView::SelectRows(并且not 设置为QAbstractItemView::SelectItems)。
    【解决方案2】:

    我的自定义模型也有同样的问题。为视图设置 dragDropOverwriteMode=false 解决了我的问题。

    【讨论】:

    • dragDropOverwriteMode 的默认值为 false,如在 QListView 和 QTreeView 子类中。另一方面,在 QTableView 子类中,该属性已设置为 true
    【解决方案3】:

    我认为是的,如果Qt::DropActionQt::MoveAction,则您必须从dropMimeData() 调用removeRows(),即您将树节点从一个地方完全移动到另一个地方。

    写下您的第二个问题,您可以在QAbstractItemModel::mimeData() 中创建您的自定义 mime 数据,并在那里对您拖动的节点的初始信息进行编码。所以,在dropMimeData()函数中你可以解码并使用它。

    【讨论】:

    • 感谢您的快速回复。我知道对自定义 mime 数据进行编码/解码,但我无法对拖动节点的索引进行编码。如何将模型索引编码为 QDataStream?
    • @user18640,例如,可以存储行号和列号,或者树项路径或者其他可以唯一标识模型索引的信息。
    • 我明白了,我将对行、列和模型索引内部 ID 进行编码,以在 dropMimeData() 中使用 QAbstractItemModel::createIndex()。谢谢。
    • 如果拖放在两个不同模型之间执行会怎样? 'removeRows' 实际上应该在源模型上调用。文档说,当“dropMimeData”返回 true 时,“removeRows”将被自动调用。
    • 这是错误的,当你从dropMimeData()返回true时,Qt会自动为你调用removeRows
    猜你喜欢
    • 1970-01-01
    • 2012-01-14
    • 1970-01-01
    • 2011-05-09
    • 1970-01-01
    • 1970-01-01
    • 2016-03-14
    • 2011-08-15
    • 2012-05-23
    相关资源
    最近更新 更多