【发布时间】:2014-04-11 04:20:46
【问题描述】:
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
请注意,如果我遇到错误的父母,我会在 index() 中提出 ValueError。
现在当我执行我的示例脚本(粘贴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() 作为函数参数的默认值(尽管它不应该被修改,所以它不应该成为问题),但没有'没有帮助。
【问题讨论】:
-
在 index() 方法中:是否可以使用名为“index”的局部变量与方法名称相同?
-
@yshurik 不错,但这应该不是问题。
-
同样在 CompletionView 的 cinstructor 中,当我猜你想要 m2.init_data 时,你调用 m1.init_data
-
@yshurik 谢谢,已更正。
标签: qt model pyqt qtreeview qabstractitemmodel