如何从包含自定义排序算法的自定义QAbstractListModel中检索正确选择的项目?
您可以通过简单地在UI中进行选择并查看控制台来测试该工具。您会看到它为所选项目打印了错误的信息。
我假设问题与我如何使用选择索引在模型中获取项目有关。
完整代码:
import os, sys
from PySide import QtGui, QtCore
class ExplorerItem(object):
def __init__(self, name, tags):
self.name = name
self.tags = tags
class ElementModel(QtCore.QAbstractListModel):
TagsRole = QtCore.Qt.UserRole + 1
NameRole = QtCore.Qt.UserRole + 2
def __init__(self, *args, **kwargs):
QtCore.QAbstractListModel.__init__(self, *args, **kwargs)
self._items = []
self._icons = {}
def rowCount(self, index=QtCore.QModelIndex()):
return len(self._items)
def addItem(self, item):
self.beginInsertRows(QtCore.QModelIndex(), self.rowCount(), self.rowCount())
self._items.append(item)
self.endInsertRows()
def getItem(self, index):
row = index.row()
if index.isValid() and 0 <= row < self.rowCount():
return self._items[row]
def data(self, index, role=QtCore.Qt.DisplayRole):
if not index.isValid():
return None
if 0 <= index.row() < self.rowCount():
item = self._items[index.row()]
if role == ElementModel.TagsRole:
return item.tags
elif role == ElementModel.NameRole:
return item.colors
elif role == QtCore.Qt.DisplayRole:
return item.name
elif role == QtCore.Qt.TextAlignmentRole:
return QtCore.Qt.AlignCenter
class ExplorerSortModel(QtGui.QSortFilterProxyModel):
def __init__(self, *args, **kwargs):
super(ExplorerSortModel, self).__init__(*args, **kwargs)
self._patterns = {}
self.setDynamicSortFilter(True)
self.setSourceModel(ElementModel())
self.sort(0, QtCore.Qt.AscendingOrder)
def set_pattern(self, role, value):
self._patterns[role] = value
def lessThan(self, left, right):
leftData = self.sourceModel()._items[left.row()]
rightData = self.sourceModel()._items[right.row()]
if leftData and rightData:
l = getattr(leftData, 'name', '')
r = getattr(rightData, 'name', '')
return l > r
return True
def filterAcceptsRow(self, sourceRow, sourceParent):
sm = self.sourceModel()
ix = sm.index(sourceRow)
if ix.isValid():
val = True
for role, fvalue in self._patterns.items():
value = ix.data(role)
val = val and self.filter(value, fvalue, role)
return val
return False
@staticmethod
def filter(value, fvalue, role):
'''
fvalue: search value
value: properties value being tested
'''
if role == ElementModel.TagsRole:
if fvalue == []:
return True
else:
return all(any(x in y for y in value) for x in fvalue)
elif role == ElementModel.NameRole:
return True
else:
return False
class QExplorerWidget(QtGui.QWidget):
def __init__(self, *args, **kwargs):
super(QExplorerWidget, self).__init__(*args, **kwargs)
self.resize(400,400)
# control
self.ui_explorer = QtGui.QListView()
self.ui_explorer.setResizeMode(QtGui.QListView.Adjust)
self.ui_explorer.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
self.ui_explorer.setMovement(QtGui.QListView.Static)
self.ui_explorer.setSpacing(10)
self.explorer_model = ExplorerSortModel()
self.ui_explorer.setModel(self.explorer_model)
self.ui_explorer_selection = self.ui_explorer.selectionModel()
lay = QtGui.QVBoxLayout()
lay.addWidget(self.ui_explorer)
self.setLayout(lay)
# connections
self.ui_explorer_selection.selectionChanged.connect(self.changed_selection)
# test data
self.explorer_model.sourceModel().addItem(ExplorerItem('John',['john','sports']))
self.explorer_model.sourceModel().addItem(ExplorerItem('Apple',['apple','fruit']))
self.explorer_model.sourceModel().addItem(ExplorerItem('Kevin',['kevin','money']))
self.explorer_model.sourceModel().addItem(ExplorerItem('Zoo',['zoo','animals']))
def changed_selection(self):
indexes = self.ui_explorer_selection.selectedIndexes()
for index in indexes:
item = self.explorer_model.sourceModel().getItem(index)
print item.name, item.tags, index
if __name__ == '__main__':
''
app = QtGui.QApplication(sys.argv)
ex = QExplorerWidget()
ex.show()
sys.exit(app.exec_())
答案 0 :(得分:1)
QModelIndex
的{{1}}属于在视图中建立的模型,在这种情况下为selectedIndexes
,因此这些索引不能直接传递给ElementModel的ExplorerSortModel
方法,因为该方法期望getItem()
属于QModelIndex
。
对于您来说,您必须使用ElementModel
方法将属于QModelIndex
的{{1}}转换为属于ExplorerSortModel
的相应QModelIndex
。
ElementModel