gpt4 book ai didi

python - QT、Python、QTreeView、自定义小部件、setData - 拖放后丢失引用

转载 作者:太空宇宙 更新时间:2023-11-03 15:59:42 24 4
gpt4 key购买 nike

这个问题与本主题Preserve QStandardItem subclasses in drag and drop中的问题类似。但对于我找不到好的解决方案的问题。该主题对更复杂的任务有部分帮助,但失败了。

当我在 QTreeView 中创建一个项目时,我将该项目放入数组中,但是当我使用拖放时,该项目被删除,我无法再访问它。我知道这是因为拖放会复制项目而不是移动它,所以我应该使用 setData。我无法将 Data 设置为对象,因为即使这样,对象也会被复制,并且我会失去对它的引用。

这是一个例子

itemsArray = self.addNewRow
def addNewRow(self)
'''some code with more items'''
itemHolder = QStandardItem("ProgressBarItem")
widget = QProgressBar()
itemHolder.setData(widget)

inx = self.model.rowCount()
self.model.setItem(inx, 0, itemIcon)
self.model.setItem(inx, 1, itemName)
self.model.setItem(inx, 2, itemHolder)
ix = self.model.index(inx,2,QModelIndex())
self.treeView.setIndexWidget(ix, widget)
return [itemHolder, itemA, itemB, itemC]

#Simplified functionality
data = [xxx,xxx,xxx]
for items in itemsArray:
items[0].data().setPercentage(data[0])
items[1].data().setText(data[1])
items[2].data().setChecked(data[2])

如果我不移动小部件,上面的代码就可以工作。当我拖/放的时候,我失去了引用,我失去了所有项目的更新,并且崩溃了。

RuntimeError: wrapped C/C++ object of type QProgressBar has been deleted

我能想到的解决这个问题的方法是在每个行/子项和名称匹配更新项上递归地循环整个 TreeView ......问题是我将每 0.5 秒刷新一次 TreeView 并且有 500+每行有 5-15 个项目。意思是...我不认为这会非常快/高效...如果我想每 0.5 秒循环超过 5000 个项目...

有人可以建议我如何解决这个问题吗?也许我可以编辑 dropEvent,这样它就不会复制/粘贴项目,而是移动项目......这样我就不会丢失数组中的对象

最佳答案

Qt 只能序列化可以存储在 QVariant 中的对象,因此它不适用于 QWidget 也就不足为奇了。但即使它可以序列化小部件,我仍然认为它不起作用,因为索引小部件属于 View ,而不是模型。

无论如何,我认为您必须单独保留对小部件的引用,并且仅在模型项中存储一个简单的键。然后,一旦项目被删除,您就可以检索小部件并在 View 中重置它们。

这是一个有效的演示脚本:

from PyQt4 import QtCore, QtGui

class TreeView(QtGui.QTreeView):
def __init__(self, *args, **kwargs):
super(TreeView, self).__init__(*args, **kwargs)
self.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
self.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
self.setAllColumnsShowFocus(True)
self.setModel(QtGui.QStandardItemModel(self))
self._widgets = {}
self._dropping = False
self._droprange = range(0)

def dropEvent(self, event):
self._dropping = True
super(TreeView, self).dropEvent(event)
for row in self._droprange:
item = self.model().item(row, 2)
self.setIndexWidget(item.index(), self._widgets[item.data()])
self._droprange = range(0)
self._dropping = False

def rowsInserted(self, parent, start, end):
super(TreeView, self).rowsInserted(parent, start, end)
if self._dropping:
self._droprange = range(start, end + 1)

def addNewRow(self, name):
model = self.model()
itemIcon = QtGui.QStandardItem()
pixmap = QtGui.QPixmap(16, 16)
pixmap.fill(QtGui.QColor(name))
itemIcon.setIcon(QtGui.QIcon(pixmap))
itemName = QtGui.QStandardItem(name.title())
itemHolder = QtGui.QStandardItem('ProgressBarItem')
widget = QtGui.QProgressBar()
widget.setValue(5 * (model.rowCount() + 1))
key = id(widget)
self._widgets[key] = widget
itemHolder.setData(key)
model.appendRow([itemIcon, itemName, itemHolder])
self.setIndexWidget(model.indexFromItem(itemHolder), widget)

class Window(QtGui.QWidget):
def __init__(self):
super(Window, self).__init__()
self.treeView = TreeView()
for name in 'red yellow green purple blue orange'.split():
self.treeView.addNewRow(name)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.treeView)

if __name__ == '__main__':

import sys
app = QtGui.QApplication(sys.argv)
window = Window()
window.setGeometry(500, 150, 600, 400)
window.show()
sys.exit(app.exec_())

关于python - QT、Python、QTreeView、自定义小部件、setData - 拖放后丢失引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40452400/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com