我在PyQt 4.8(Python 2.7)中实现了自己的QAbstractItemModel:
class FriendListModel(QtCore.QAbstractItemModel):
def __init__(self, groups, client):
QtCore.QAbstractItemModel.__init__(self)
self.root = groups
self.client = client
self.header = ['Player', 'Land', 'Rating', '#']
def columnCount(self, parent):
return len(self.header);
def headerData(self, col, orientation, role):
if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
return self.header[col]
return None
def rowCount(self, parentIndex):
pointer = parentIndex.internalPointer()
# if root level
if pointer is None:
return len(self.root)
# if on FriendGroup level
if hasattr(pointer, 'users'):
return len(pointer.users)
return 0
def index(self, row, column, parentIndex):
pointer = parentIndex.internalPointer()
# if root element, use root list
if pointer is None:
return self.createIndex(row, column, self.root[row])
# if on FriendGroup level
if hasattr(pointer, 'users'):
return self.createIndex(row, column, pointer.users[row])
return self.createIndex(row, column, None)
def data(self, index, role):
if not index.isValid():
return None
pointer = index.internalPointer()
if role == QtCore.Qt.DecorationRole and isinstance(pointer, User) and index.column() == 0:
if pointer.avatarNotLoaded:
pointer.loadPixmap()
if not pointer.avatarNotLoaded:
print 'loaded'
self.emit(QtCore.SIGNAL('modelChanged'), index, index)
return pointer.pix
if role == QtCore.Qt.UserRole:
if isinstance(pointer, FriendGroup):
return None
if index.column() == 0:
return pointer.username
if role == QtCore.Qt.DisplayRole or role == QtCore.Qt.UserRole:
if isinstance(pointer, FriendGroup):
if index.column() == 0:
return pointer.name
return None
else:
if index.column() == 1:
return pointer.country
if index.column() == 2:
return pointer.rating
if index.column() == 3:
return '#'
return pointer.name
return None
def parent(self, index):
if not index.isValid():
return QtCore.QModelIndex()
pointer = index.internalPointer()
if hasattr(pointer, 'users'):
return QtCore.QModelIndex()
else:
row = 0 if pointer.group == 'online' else 1
return self.createIndex(row, 0, pointer.group)
在运行时,我向模型添加元素:
def addFriend(self, groupIndex, username):
'''
groupIndex: 0 = online, 1 = offline
'''
self.updateTopLabel()
n = len(self.model.root[groupIndex].users)
self.model.beginInsertRows(self.model.index(groupIndex, 0, QtCore.QModelIndex()), n, n)
self.model.root[groupIndex].addUser(username)
self.model.endInsertRows()
所有似乎都是正确的(来自ui),但如果我尝试从ModelIndex调用internalPointer,应用程序崩溃了。 (APPCRASH,python.exe不再工作,没有stackstrace,...)
@QtCore.pyqtSlot(QtCore.QPoint)
def on_friendlist_customContextMenuRequested(self, pos):
modelIndex = self.friendlist.indexAt(pos)
if modelIndex == None or not modelIndex.isValid():
return
pointer = modelIndex.internalPointer()
...
我不知道我做错了什么。 有什么提示怎么调试呢?
我搜索了类似的问题,但没有任何结果。
如果删除QSortFilterProxyModel,则一切正常。
#proxy = QtGui.QSortFilterProxyModel()
#proxy.setSourceModel(self.model)
#proxy.setSortRole(QtCore.Qt.UserRole)
#self.friendlist.setModel(proxy)
self.friendlist.setModel(self.model)
我发现了自己的错误。我使用了QSortFilterProxyModel并忘了映射回来。
@QtCore.pyqtSlot(QtCore.QPoint)
def on_friendlist_customContextMenuRequested(self, pos):
modelIndex = self.friendlist.indexAt(pos)
if modelIndex == None or not modelIndex.isValid():
return
pointer = self.proxy.mapToSource(modelIndex).internalPointer()
if pointer == None:
return
playername = pointer.name
print playername
https://github.com/IDragonfire/lobby/commit/6c49571f5619e85bb9cea76d84296f158ef81a9b