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_())
使用 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_())