我想使用PyQt + QML方法创建一个以列表形式排列的GUI元素的简单列表。元素表示具有两个主要属性的项目: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提供模型(您无需对单个子类进行子类化,尽管我找到了解决方法。有效案例)。
蟒蛇:
#!/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
}
}
}
因此,您将获得如下内容: