在 QML 中使用 ListModel (Python/Pyside6)

问题描述 投票:0回答:1

我在 QML 中有一个 ListView,想要用我在 Python 中创建的 AbstractListModel 中的数据填充它。

AbtractListModel.py(我删除了像 rowCount() 这样的方法以保持示例清晰)

class StudentModel(QAbstractListModel):
    def __init__(self)
        super().__init()
        self.studentList = []
        self.studentList.append(Student("Peter", 22)

    def data(self, index: QtCore.QModelIndex, role: int = ...) -> typing.Any:
        if role == QtCore.Qt.DisplayRole:
            return self.studentList[index]
        return None

学生.py

class Student(object):
    name = ""
    age = 0

    def __init__(self, name, age):
        self.name = name
        self.age = age

ListView.qml

ListView {
   model: studentModel
    
   delegate: Rectangle {
       Text{ text: #name }
       Text{ text: #age }
   }
}

我如何访问代表中学生的姓名和年龄,以向他们展示我在哪里使用了“#name”和“#age”?

python qml pyside6
1个回答
4
投票

您至少必须实现 QAbstractListModel 的 rowCount、data 和 roleNames 方法:

from __future__ import annotations

import os
import sys
import typing
from dataclasses import dataclass, fields
from pathlib import Path

from PySide6.QtCore import (
    QAbstractListModel,
    QByteArray,
    QCoreApplication,
    QModelIndex,
    QObject,
    Qt,
    QUrl,
)
from PySide6.QtGui import QGuiApplication
from PySide6.QtQml import QQmlApplicationEngine


CURRENT_DIRECTORY = Path(__file__).resolve().parent


@dataclass
class Student:
    name: str = ""
    age: int = 0


class StudentModel(QAbstractListModel):
    def __init__(self, parent: QObject | None) -> None:
        super().__init__()
        self._studend_list = []
        self._studend_list.append(Student("Peter", 22))

    def data(self, index: QModelIndex, role: int = Qt.DisplayRole) -> typing.Any:
        if 0 <= index.row() < self.rowCount():
            student = self._studend_list[index.row()]
            name = self.roleNames().get(role)
            if name:
                return getattr(student, name.decode())

    def roleNames(self) -> dict[int, QByteArray]:
        d = {}
        for i, field in enumerate(fields(Student)):
            d[Qt.DisplayRole + i] = field.name.encode()
        return d

    def rowCount(self, index: QModelIndex = QModelIndex()) -> int:
        return len(self._studend_list)

    def add_student(self, student: Student) -> None:
        self.beginInsertRows(QModelIndex(), self.rowCount(), self.rowCount())
        self._studend_list.append(student)
        self.endInsertRows()


def main() -> None:
    app = QGuiApplication(sys.argv)

    engine = QQmlApplicationEngine()

    student_model = StudentModel()
    engine.rootContext().setContextProperty("studentModel", student_model)

    filename = os.fspath(CURRENT_DIRECTORY / "main.qml")
    url = QUrl.fromLocalFile(filename)

    def handle_object_created(obj: QObject | None, obj_url: QUrl) -> None:
        if obj is None and url == obj_url:
            QCoreApplication.exit(-1)

    engine.objectCreated.connect(handle_object_created, Qt.QueuedConnection)
    engine.load(url)

    student_model.add_student(Student("wileni", 23))

    sys.exit(app.exec())


if __name__ == "__main__":
    main()
import QtQuick
import QtQuick.Controls

ApplicationWindow {
    id: root

    width: 640
    height: 480
    visible: true

    ListView {
        model: studentModel
        anchors.fill: parent

        delegate: Row {
            Text {
                text: model.name
            }

            Text {
                text: model.age
            }

        }

    }

}
© www.soinside.com 2019 - 2024. All rights reserved.