python - 带有 QML 和 PyQt 的项目列表
问题描述
我想创建一个简单的 GUI 元素列表,使用 PyQt + QML 方法排列在列表中。元素代表具有两个主要属性的项目:name
和state
。最初,该列表填充了一些代码内对象,例如来自 QT 设置存储。问题是,我想将从我的类(专用模块)的存储中检索到的每个条目包装起来。在伪代码中:
from my_module import Project
initial_list = [{
name: 'Spaceship',
state: 'In progress'
}, {
name: 'Aircraft',
state: 'Done'
}, {
name: 'Truck',
state: 'Broken'
}]
projects = [Project(p) for p in initial_list]
用户可以单击该项目并使用它执行一些任务(这就是我希望该元素成为Project
实例的原因)。
我知道我应该有一个代表数据的模型,但我发现我发现的分散的例子很困难。我应该有单个元素的模型以及整个列表模型吗?如何将Project
实例封装在QObject
子类中?我最后的尝试是QAbstractListModel
用作模型并ListView
用作视觉表示。你能给我一个最小的完整例子吗?
解决方案
猜猜我已经自己想通了。对于所有想要以某种方式重复该任务的人:您确实需要子类化QAbstractItemModel
( QAbstractListModel
) 以为您的 QML 提供模型(您不需要子类化单个项目,尽管我在有效情况下找到了方法)。
Python:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
from PyQt5.QtCore import QCoreApplication, QUrl, QAbstractItemModel, pyqtProperty, QAbstractListModel, QModelIndex, \
QObject, QVariant, Qt
from PyQt5.QtGui import QGuiApplication
from PyQt5.QtQuick import QQuickView
import mylib
class ProjectListItem(QObject):
def __init__(self, project: mylib.Project, parent=None):
super().__init__(parent)
self.project = project
@pyqtProperty('QString')
def name(self):
return self.project.path.name
@pyqtProperty('QString')
def state(self):
return str(self.project.state)
class ProjectsList(QAbstractListModel):
def __init__(self, projects: list, parent=None):
super().__init__(parent)
self.projects = projects
def rowCount(self, parent=None, *args, **kwargs):
return len(self.projects)
def data(self, index: QModelIndex, role=None):
# print(index, role)
if role == Qt.DisplayRole:
return self.projects[index.row()]
def addProject(self, project):
self.beginInsertRows(QModelIndex(), self.rowCount(), self.rowCount())
self.projects.append(project)
self.endInsertRows()
if __name__ == '__main__':
app = QGuiApplication(sys.argv)
projects = ProjectsList([])
projects.addProject(ProjectListItem(mylib.Project('Abc')))
projects.addProject(ProjectListItem(mylib.Project('Def')))
projects.addProject(ProjectListItem(mylib.Project('Ghi')))
view = QQuickView()
view.setResizeMode(QQuickView.SizeRootObjectToView)
view.rootContext().setContextProperty('projectsModel', projects)
view.setSource(QUrl('main.qml'))
sys.exit(app.exec_())
QML:
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("PyQt5 love QML")
color: "whitesmoke"
GridLayout {
columns: 2
rows: 1
ListView {
width: 200; height: 250
model: projectsModel
delegate: Item {
id: projectListItem
width: ListView.view.width
height: 40
Column {
Text { text: '<b>Name:</b> ' + display.name }
Text { text: '<b>State:</b> ' + display.state }
}
MouseArea {
anchors.fill: parent
onClicked: { projectListItem.ListView.view.currentIndex = index; }
}
}
highlight: Rectangle { color: "lightsteelblue"; radius: 5 }
focus: true
}
}
}
那么你会得到这样的东西:
推荐阅读
- postgresql - 使用 Power BI 中的 DAX 度量对某个时间段进行滚动平均
- c++ - 远裁剪平面之外的对象在透视图中渲染
- r - 如何在 R 中创建 4D 等高线图?
- html - 永久可用文件下载以进行互联网速度测试
- ruby-on-rails - 尽管接收到值,但 Ransack 搜索始终使用“LIKE NULL”检查 SQL 语句
- umbraco - Umbraco,在子节点中显示来自媒体选择器的图像
- python - 我可以轻松剪辑由 vtkCylinderSource 生成的圆柱体吗?
- assembly - DOSBOX-X Bug:换行向右偏移
- javascript - React Router Dom 组件在 App.js 中呈现,但不是作为单独的组件
- django - 中间模型中的 ManyToManyField 或 ForeignKeys?