PyQt 5 QStandardItem 存储旧父项

PyQt 5 QStandardItem Storing Old Parent

使用 PyQt 5 我一直在尝试找到一种方法,使用 QStandardItemModel 和 QStandarItems 从 QTreeView 情况下对项目的拖放操作中获取旧父对象。

我真的很想尽可能避免创建自己的模型。

我目前的尝试是在将当前父项目创建为 "old parent" 时将其存储在项目中,并且不应在移动中对其进行更新,以便我可以引用它来更新旧父项目中的值然后将移动项目中的 "old parent" 更新为新的当前父项。

虽然我似乎无法让它工作,但这是我在创建项目时尝试用来存储 "old parent" 的代码:

item.setData(parent.index(),(Qt.UserRole+3))

当我 运行 这个但是我得到以下错误:

QVariant::save: unable to save type 'QModelIndex' (type id: 42).

此时我无法引用旧父...

我找到了一个使用 c++ 和很多 "pointer casting" 的参考,但我不知道如何将代码转换为 Python 和 PyQt 5。

C++ 参考:https://forum.qt.io/topic/1690/qvariant-save-load-unable-to-save-type-x/19

感谢您的帮助!

该模型有 some signals 每当插入或删除项目的子项时都会触发,因此这些可用于自动更新项目。

经过一些实验,我发现信号需要与queued connection一起使用,这样模型才有机会完全更新:

model.rowsInserted.connect(slot, type=QtCore.Qt.QueuedConnection)
model.rowsRemoved.connect(slot, type=QtCore.Qt.QueuedConnection)

但除此之外,实现起来非常简单。无需在项目中存储任何额外信息,因为可以动态执行更新。

这是一个基本的演示脚本:

from PyQt5 import QtCore, QtGui, QtWidgets

class Window(QtWidgets.QTreeView):
    def __init__(self):
        super(Window, self).__init__()
        self.setDragDropMode(QtWidgets.QAbstractItemView.InternalMove)
        self.setDragDropOverwriteMode(False)
        self.header().hide()
        model = QtGui.QStandardItemModel(self)
        model.rowsInserted.connect(
            self.sumItems, type=QtCore.Qt.QueuedConnection)
        model.rowsRemoved.connect(
            self.sumItems, type=QtCore.Qt.QueuedConnection)
        self.setModel(model)
        parent = model.invisibleRootItem()
        for index in range(3):
            item = QtGui.QStandardItem('0')
            parent.appendRow(item)
            for row in range(1, 5):
                child = QtGui.QStandardItem(str(row))
                item.appendRow(child)
        self.expandAll()

    def sumItems(self, index, first, last):
        if index.isValid():
            total = 0
            parent = self.model().itemFromIndex(index)
            for row in range(parent.rowCount()):
                child = parent.child(row)
                if child is not None:
                    total += int(child.text())
            parent.setText(str(total))

if __name__ == '__main__':

    import sys
    app = QtWidgets.QApplication(sys.argv)
    window = Window()
    window.setGeometry(700, 100, 250, 300)
    window.show()
    sys.exit(app.exec_())