4

我应该如何在 PyQt 中创建 QAbstractListModel 并将其与 QML ListView 一起使用?

4

3 回答 3

3

如果其他人正在寻找答案,我制作了一个小应用程序,它使用 QAbstractListModel 的子类连接到演员数据库,并根据 @fgungor 发布的示例在 QGridView 中显示缩略图。(PyQt5)

主.py

import sys, models
from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QApplication
from PyQt5.QtQuick import QQuickView

if __name__ == '__main__':

    # Prints QML errors
    def handleStatusChange(status):
        if status == QQuickView.Error:
            errors = appLabel.errors()
            if errors:
                print (errors[0].description())



    myApp = QApplication(sys.argv)
    appLabel = QQuickView()
    appLabel.statusChanged.connect(handleStatusChange)
    model = models.ActorModel(DB_PATH)
    ctxt = appLabel.rootContext()
    ctxt.setContextProperty('myModel', model)
    appLabel.setSource(QUrl('./qml/main/main.qml'))

    try:
        sys.exit(myApp.exec_())
    except:
        print("Exiting")

模型.py

import db
from PyQt5.QtCore import QAbstractListModel, Qt, pyqtSlot


class ActorModel(QAbstractListModel):
    NameRole = Qt.UserRole + 1
    ThumbRole = Qt.UserRole + 2

    _roles = {NameRole: b"name", ThumbRole: b"thumb"}

    def __init__(self, db_path):
        super(ActorModel, self).__init__()
        self._actors = []
        self._db = db.Database(db_path)


    def update(self, search_term):
        self.beginResetModel()
        self._actors = self._db.actor_search(search_term)
        self.endResetModel()

    # Reacts to onTextChanged event of searchBar (in QML code)
    @pyqtSlot(str)
    def search_input(self,search_input):
        if len(search_input) > 3:
            print (search_input)
            self.update(search_input)

    def rowCount(self, parent=None, *args, **kwargs):
        return len(self._actors)

    def data(self, QModelIndex, role=None):
        row = QModelIndex.row()
        if role == self.NameRole:
            return self._actors[row]["name"]

        if role == self.ThumbRole:
            return self._actors[row]["thumbnail"]

    def roleNames(self):
        return self._roles

数据库.py:

import sqlite3


class Database:

    def __init__(self, db_path):
        self.db_path = db_path
        self.sqlite_db = sqlite3.connect(self.db_path)
        self.sqlite_db.row_factory = sqlite3.Row
        self.cursor = self.sqlite_db.cursor()

    def actor_search(self, actor_name):
        self.cursor.execute('SELECT Actors.Id,Actors.Name,Actors.thumbnail AS thumbnail FROM Actors '
                                'WHERE Actors.Name LIKE \'%{}%\' ORDER BY Actors.Name'.format(actor_name))
        return self.cursor.fetchall()

main.qml:

import QtQuick 2.8
import QtQuick.Window 2.2
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.1

Window {
    id: root
    visible: true
    title: 'Actor Exploer'
    width: 1280
    height: 720

    ColumnLayout {
        id: mainLayout
        anchors.fill: parent

        Row {
            Layout.fillWidth: true

            TextArea {
                id: searchBar
                placeholderText: "Input actor name"
                Layout.fillWidth: true
                width: 600
                onTextChanged: myModel.search_input(searchBar.text)                
            }


        }

        GridView {

            id: gridView
            keyNavigationWraps: true
            Layout.fillWidth: true
            Layout.fillHeight: true
            cellWidth: 220
            cellHeight: 320

            model: myModel // QML connection to python model
            delegate: Rectangle {
                id: thumb_frame
                height: 330
                width: 200
                Image {
                    id: actorThumb
                    asynchronous: true
                    source: "file:///" + thumb  // Access to the ThumbRole in ActorModel in our python code
                    smooth: true
                    sourceSize.width: 200
                    sourceSize.height: 300
                    height: 300
                    width: 200
                    anchors.left: thumb_frame.left
                    anchors.top: thumb_frame.top

                    onStatusChanged: {
                        if (actorThumb.status == Image.Error)
                            actorThumb.source = 'PLACEHOLDER_IMAGE_PATH'
                    }
                }

                Text {
                    anchors.top: actorThumb.bottom
                    anchors.horizontalCenter: actorThumb.horizontalCenter
                    text: name // Access to the NameRole in ActorModel in our python code
                }


        }
    }
}
于 2017-03-10T14:32:24.117 回答
2

您需要设置它的角色名称才能在 QML 中使用它;

http://doc.qt.io/qt-4.8/qabstractitemmodel.html#setRoleNames

于 2010-12-06T16:06:52.913 回答
1

没有使用过 PyQT,但你可以在这里找到一个最小的工作示例:http: //doc.qt.nokia.com/stable/qdeclarativemodels.html

如果您检查包含 的示例,class Animal {...}您会发现您必须为要提供的不同字段定义角色。并且至少您必须定义返回给定索引的相应字段值的 data() 函数。此外,您可能需要自己的自定义方法来插入和删除。希望这可以帮助...

于 2011-03-16T09:59:03.350 回答