python - 如何在 QListView 中显示从 QAbstractListModel 派生的自定义模型
问题描述
我将在下面基于 QAbstractListModel 提供的自定义数据模型将在两个视图中:基于 QWidget 的控制界面和基于 QML 的“仪表板”。基于 QWidget 的控制端必须在自定义委托中显示模型项(模型行),每个数据点都在下面描述的模型中声明自定义角色,并且至少提供一个按钮用于调用编辑器小部件以更改角色提供的数据点(即日期或特定项目的开始时间)。
class ScheduleModel(QAbstractListModel):
SfiRole = Qt.UserRole + 1
NameRole = Qt.UserRole + 2
ClsRole = Qt.UserRole + 3
FlagRole = Qt.UserRole + 4
OwnrRole = Qt.UserRole + 5
RecordRole = Qt.UserRole + 6
DeptRole = Qt.UserRole + 7
DateStrRole = Qt.UserRole + 8
HourRole = Qt.UserRole + 9
EstTimeRole = Qt.UserRole + 10
StatusRole = Qt.UserRole + 11
def __init__(self, parent=None):
super().__init__(parent)
self._data = []
def rowCount(self, parent=QModelIndex()):
return len(self._data)
@Slot()
def updateSchedule(self, schedule_items: list):
self.beginResetModel()
self._data = schedule_items
self.endResetModel()
def data(self, index=QModelIndex(), role: int = Qt.DisplayRole):
if 0 <= index.row() < self.rowCount() and index.isValid():
item = self._data[index.row()]
if role == self.SfiRole:
return item.sfi
elif role == self.NameRole:
return item.item_name
elif role == self.ClsRole:
return item.class_attendance
elif role == self.FlagRole:
return item.flag_attendance
elif role == self.OwnrRole:
return item.owner_attendance
elif role == self.RecordRole:
return item.record_status
elif role == self.DeptRole:
return item.responsible_dept
elif role == self.DateStrRole:
return item.date
elif role == self.HourRole:
return item.start_hour
elif role == self.EstTimeRole:
return item.est
elif role == self.StatusRole:
return "Passive"
else:
return None
def roleNames(self):
roles = dict()
roles[self.SfiRole] = b'sfiRole'
roles[self.NameRole] = b'nameRole'
roles[self.ClsRole] = b'clsRole'
roles[self.FlagRole] = b'flagRole'
roles[self.OwnrRole] = b'ownrRole'
roles[self.RecordRole] = b'recordRole'
roles[self.DeptRole] = b'deptRole'
roles[self.DateStrRole] = b'dateStrRole'
roles[self.HourRole] = b'hourRole'
roles[self.EstTimeRole] = b'estTimeRole'
roles[self.StatusRole] = b'statusRole'
return roles
上述模型用于保留数据并通过索引和角色名称进行调用。我选择使用 QListView 和 QStyledItemDelegate 在基于 Qt 的视图中显示数据。就我现在而言,我必须开发一种用于显示和基本模型的绘制方法 Qt 使用 DisplayRole 从数据模型中读取字符串。但正如您从模型中看到的那样,我没有为 DispplayRole 提供便利,并且我有几个自定义角色,用于为模型中的每个项目显示数据点。 我尝试为继承自 QStyledItemDelegate 的委托创建一个绘制方法,以绘制与此类似的内容。例如,我在图片上标记了角色。简而言之,问题是:是否可以覆盖 QStyledItemDelegate 的绘制方法以显示自定义数据角色提供的字符串,并显示是否可以在自定义委托中绘制用于调用编辑器小部件的按钮?
解决方案
我试图创建一个基于 QWidget 的解决方案,但我失败了。之后尝试创建和绘制方法以实现我想要的外观。我将在下面留下我的委托类和绘制方法作为复杂委托的示例。
class TestItemDelegate(QStyledItemDelegate):
"""A delegate to show test items in listview in qt side"""
def __init__(self, parent=None) -> None:
super().__init__(parent)
self.model = self.parent().model()
def paint(self, painter: QPainter,
option: QStyleOptionViewItem, index: QModelIndex):
model_ind = index.model()
canvas = option.rect.getRect()
painter.setRenderHint(QPainter.Antialiasing, on=True)
# Supplying data from model
sfi = index.data(model_ind.SfiRole)
name = index.data(model_ind.NameRole)
cls_att = index.data(model_ind.ClsRole)
flg_att = index.data(model_ind.FlagRole)
ownr_att = index.data(model_ind.OwnrRole)
# rec_stat = index.data(model_ind.RecordRole)
resp_dept = index.data(model_ind.DeptRole)
date_str = index.data(model_ind.DateStrRole)
hour_str = index.data(model_ind.HourRole)
est_duration = index.data(model_ind.EstTimeRole)
# status = model_ind.data(index, model_ind.StatusRole)
# Frame and Background(s)
pen = QPen()
pen.setColor("Black")
pen.setWidth(2)
painter.setPen(pen)
painter.drawRoundedRect(option.rect, 10, 10)
painter.setPen(Qt.blue)
# Coordinates for delegate background
x, y, w, h = canvas
# Drawing of the texts
painter.drawText(
QRect(x + 50, y, w-200, h//2),
Qt.AlignVCenter, name)
painter.drawText(
QRect(x, y, h, h),
Qt.AlignCenter, sfi)
painter.drawText(
QRect(x+w-150, y, 50, h//3),
Qt.AlignVCenter,
"C:{}".format('-' if cls_att == '' else cls_att))
painter.drawText(
QRect(x+w-150, y+h//3, 50, h//3),
Qt.AlignVCenter,
"F:{}".format('-' if flg_att == '' else flg_att))
painter.drawText(
QRect(x+w-150, y + 2*h//3, 50, h//3),
Qt.AlignVCenter,
"O:{}".format('-' if ownr_att == '' else ownr_att))
painter.drawText(
QRect(x+50, y+h//2, w//3, h//2),
Qt.AlignVCenter, resp_dept)
painter.drawText(
QRect(x+w-100, y, 100, h//2),
Qt.AlignCenter, date_str.strftime('%d-%m-%Y')
)
painter.drawText(
QRect(x+w-100, y+h//2, 50, h//2),
Qt.AlignCenter, hour_str.strftime('%H:%M')
)
painter.drawText(
QRect(x+w-50, y+h//2, 50, h//2),
Qt.AlignCenter, est_duration
)
def createEditor(self, parent, option, index):
print(type(parent))
def sizeHint(self, option, index):
size = QSize(300, 50)
return size
我通过模型的 flags 方法将模型设置为可选择和可编辑。
def flags(self, index):
if index.isValid():
return (Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsEditable)
return super().flags(index)
我现在正在创建编辑器小部件和相关方法。在我获得可行的解决方案后,可能会更新此答案以留下全面的答案。
推荐阅读
- python - 无法使用 partitionByInstrument 将文件分成几部分
- node.js - 在 Windows 64 位系统上,'ng' 未被识别为内部或外部命令
- java - Eclipse 安装失败并出现错误
- reactjs - 如何减少生产中的 reactjs 文件大小?
- ios - 金属着色器在缓冲区中插入值
- android - 更改对象/类
- string - Shell.Application getDetailsOf jpg Exif DateTaken 无效 DateTime
- ios - 避免在应用程序处于前台时显示通知警报
- javascript - 访问多维数组中的每个值
- ios - 如何在ios中将应用程序上传到应用程序商店时解决此问题