在使用 QListView
显示列表数据时,比较常用的是 QStringListModel
,但 QStringListModel
的功能比较单调,只能使用字符串,也修改不了字体颜色、背景色等多种属性。
要实现传入对象,修改颜色等更多的功能,需要自定义数据模型。
创建
创建一个基于 PyQt5.QtCore.QAbstractListModel
类的数据模型。
class MyListModel(QAbstractListModel):
def __init__(self):
super().__init__()
self._data_list = [] # 数据list,保存所有数据
继承后有 data()
和 rowCount()
两个方法必须要实现。
def data(self, index: QModelIndex, role: int = ...):
"""
继承父类,必须有。设置不同类型调用返回数据
:param index: 索引
:param role: 要获取的数据类型
:return:
"""
# 设置表格显示使用的数据
if index.isValid() or (0 <= index.row() < len(self._data_list)):
if role == Qt.DisplayRole:
return QVariant(self._data_list[index.row()]['name'])
elif role == Qt.BackgroundRole:
if self._data_list[index.row()].id != 0:
return QBrush(QColor(84, 255, 159))
else:
return QBrush(QColor(255, 255, 255))
else:
return QVariant()
def rowCount(self, parent: QModelIndex = ...) -> int:
"""
继承父类,必须有。返回数据总行数
:param parent:
:return:
"""
return len(self._data_list)
比较常用的 role
有
- Qt.DisplayRole:显示在界面上的内容
- Qt.ForegroundRole:前景色(通常是文字颜色)
- Qt.BackgroundRole:背景色(整行)
其他类型可以参考 ItemDataRole
需要注意的是 role
的定义是通用的,一些 role
在 QListView
里并不会被使用。比如 StatusTipRole
。
增删改清
def add_item(self, item_data):
"""
自定义。添加单个数据
:param item_data: 数据
:return:
"""
if item_data:
self.beginInsertRows(QModelIndex(), len(self._data_list), len(self._data_list) + 1)
self._data_list.append(item_data)
self.endInsertRows()
def delete_item(self, row):
"""
自定义。删除数据
:param row: 索引
:return:
"""
self.beginRemoveRows(QModelIndex(), row, row - 1)
del self._data_list[row]
self.endRemoveRows()
def update_item(self, index, new_item):
"""
自定义。更新数据
:param index: 索引
:param new_item: 新数据
:return:
"""
self._data_list[index.row()] = new_item
self.dataChanged(index, index, Qt.BackgroundRole)
def clear(self):
"""
清空数据
:return:
"""
self.beginResetModel()
self._data_list.clear()
self.endResetModel()
需要注意的是,在增删自定义数据列表的时候,需要在操作前后 begin
和 end
,这样操作的结果才会同步到 UI 上。
修改数据数据时不需要 begin
和 end
,但是需要调用 dataChanged()
以通知 UI 刷新数据,在通知时还需要指定变化的起始行,结束行和有变化的 role
。
不调用也可以,当修改的那一行从未选中状态变成选中状态时也会自动刷新数据。
也可以通过连续调用
QListView
的clearFocus()
和setFocus()
来实现当前列表所有可见数据的刷新。
使用
使用上和 QStringListModel
一样,创建一个 Model 对象,然后赋值给 listView 即可。
list_model = MyListModel()
self.listView.setModel(list_model)