【问题标题】:PyQt 5 QStandardItem Storing Old ParentPyQt5 QStandardItem 存储旧父母
【发布时间】:2017-01-07 06:16:10
【问题描述】:

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

如果可能的话,我真的很想避免创建自己的模型。

我当前的尝试是将当前父项创建为“旧父项”时将其存储在项目中,并且不应在移动中更新它,因此我可以引用它更新旧父项中的值,然后更新移动项目中的“旧父级”到新的当前父级。

我似乎无法让它工作,这是我试图在创建项目时用来存储“旧父级”的代码:

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

当我运行它时,我收到以下错误:

QVariant::save: 无法保存类型“QModelIndex”(类型 ID:42)。

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

我找到了一个使用 c++ 和大量“指针转换”的参考资料,但我不知道如何将代码转换为 Python 和 PyQt 5。

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

感谢您的帮助!

【问题讨论】:

  • 在您当前的尝试中,一旦您拖放一个项目,其所有子项(及其所有子项等)的存储索引将立即失效。所以这种方法不管如何实施都是行不通的。您这样做要解决的实际问题是什么?
  • 当我从中删除一行项目并将其放在树中的另一个位置时,我正在尝试更新列的总和。每个父节点都有一个总和项,该总和项在列中保留子项的总和,我试图让该总和项在我移入和移出项目时更新。我希望这是有道理的!

标签: python drag-and-drop pyqt pyqt5 qstandarditemmodel


【解决方案1】:

该模型有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_())

【讨论】:

  • 这正是我想要的!我完全错过了 WRT rowsInserted 和 rowsRemoved 的文档。例如,模型中的 rowCount 不会通过将子项添加到项(使用 item.appendRow())来更改,但这些信号仍会发送...
猜你喜欢
  • 2017-06-30
  • 1970-01-01
  • 2023-01-10
  • 2017-09-11
  • 1970-01-01
  • 1970-01-01
  • 2011-03-09
  • 2011-06-17
  • 1970-01-01
相关资源
最近更新 更多