QSortFilterProxyModel
我遇到了一个奇怪的问题。我在QTreeView中执行此操作:
class CompletionView(QTreeView):
def __init__(self, parent=None):
super().__init__(parent)
self.setModel(QSortFilterProxyModel())
m1 = CompletionModel()
print("Model 1: {}".format(m1))
m1.init_data({'test1': [('one', 'two'), ('three', 'four')]})
self.model().setSourceModel(m1)
self.expandAll()
m2 = CompletionModel()
print("Model 2: {}".format(m2))
m2.init_data({'test': [('five', 'six'), ('seven', 'eight')]})
self.model().setSourceModel(m2)
self.expandAll()
这是我的CompletionModel,我无法真正简化:
class CompletionModel(QAbstractItemModel):
def __init__(self, parent=None):
super().__init__(parent)
self._id_map = {}
self._root = CompletionItem([""] * 2)
self._id_map[id(self._root)] = self._root
def _node(self, index):
if index.isValid():
return self._id_map[index.internalId()]
else:
return self._root
def init_data(self, data):
for (cat, items) in data.items():
newcat = CompletionItem([cat], self._root)
self._id_map[id(newcat)] = newcat
self._root.children.append(newcat)
for item in items:
newitem = CompletionItem(item, newcat)
self._id_map[id(newitem)] = newitem
newcat.children.append(newitem)
def columnCount(self, parent=QModelIndex()):
return self._root.column_count()
def rowCount(self, parent=QModelIndex()):
if parent.column() > 0:
return 0
if not parent.isValid():
pitem = self._root
else:
pitem = self._id_map[parent.internalId()]
return len(pitem.children)
def data(self, index, role=Qt.DisplayRole):
if not index.isValid():
return QVariant()
try:
item = self._id_map[index.internalId()]
except KeyError:
return QVariant()
try:
return QVariant(item.data(index.column(), role))
except (IndexError, ValueError):
return QVariant()
def headerData(self, section, orientation, role=Qt.DisplayRole):
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
return QVariant(self._root.data(section))
return QVariant()
def index(self, row, column, parent=QModelIndex()):
if parent.model() is not None and parent.model() is not self:
raise ValueError("Model mismatch: parentmodel {}, self {}".format(parent.model(), self))
if (0 <= row < self.rowCount(parent) and
0 <= column < self.columnCount(parent)):
pass
else:
return QModelIndex()
if not parent.isValid():
parent_item = self._root
else:
parent_item = self._id_map[parent.internalId()]
child_item = parent_item.children[row]
if child_item:
index = self.createIndex(row, column, id(child_item))
self._id_map.setdefault(index.internalId(), child_item)
return index
else:
return QModelIndex()
def parent(self, index):
if not index.isValid():
return QModelIndex()
item = self._id_map[index.internalId()].parent
if item == self._root or item is None:
return QModelIndex()
return self.createIndex(item.row(), 0, id(item))
class CompletionItem():
def __init__(self, data, parent=None):
self.parent = parent
self.children = []
self._data = data
def data(self, column, role=Qt.DisplayRole):
if role == Qt.DisplayRole:
return self._data[column]
else:
raise ValueError("Invalid role {}".format(role))
def column_count(self):
return len(self._data)
def row(self):
if self.parent:
return self.parent.children.index(self)
return 0
注意如果我的父母错了,我会在ValueError
中提出index()
。
现在当我执行我的示例脚本(粘贴in my pastebin)时,会发生这种情况:
Model 1: <__main__.CompletionModel object at 0x7fefe1ccd770>
Model 2: <__main__.CompletionModel object at 0x7fefe1ccd808>
Traceback (most recent call last):
File "model.py", line 59, in index
raise ValueError("Model mismatch: parentmodel {}, self {}".format(parent.model(), self))
ValueError: Model mismatch: parentmodel <__main__.CompletionModel object at 0x7fefe1ccd770>, self <__main__.CompletionModel object at 0x7fefe1ccd808>
Traceback (most recent call last):
File "model.py", line 59, in index
raise ValueError("Model mismatch: parentmodel {}, self {}".format(parent.model(), self))
ValueError: Model mismatch: parentmodel <__main__.CompletionModel object at 0x7fefe1ccd770>, self <__main__.CompletionModel object at 0x7fefe1ccd808>
为什么会这样?我在模型中做错了什么,或者这是一个Qt错误?
我还尝试使用None
作为标记值,我使用QModelIndex()
作为函数参数的默认值(虽然它不应该被修改,所以它应该不是问题) ,这没有帮助。
答案 0 :(得分:2)
当您重置之前,可能有一些参考文献被保留在上一个模型的位置,因此您会收到“模型不匹配”错误。
当我尝试您的示例时,我发现在重置之间将源模型设置为None
可以消除错误:
self.model().setSourceModel(m1)
...
self.model().setSourceModel(None) # clear the current model
...
self.model().setSourceModel(m2)
答案 1 :(得分:-2)
记得你遇到这个问题的原因。
实际上,它是具有默认值的方法参数的Python特殊性。 Python特殊性是这样的参数是static_variable。 所以当第一次打电话时:
m1.index(1,2,parent_from_model_m1);
以后再打电话:
m2.index(3,4)
然后对于第二次调用,“parent”将获得默认值 - 而不是QModelIndex()但是parent_from_model_m1(“parent”参数作为静态变量记住第一次调用时的parent_from_model_m1)
解决方案应该很简单 - 删除默认值。