代码之家  ›  专栏  ›  技术社区  ›  reshefm

pyqt和qml-如何创建自定义数据模型

  •  3
  • reshefm  · 技术社区  · 14 年前

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

    3 回复  |  直到 8 年前
        1
  •  1
  •   HWM-Rocker    10 年前

    您需要设置它的角色名,以便在QML中使用它;

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

        2
  •  1
  •   fgungor    14 年前

    尚未使用Pyqt,但您可以在此处找到最小工作样本: http://doc.qt.nokia.com/stable/qdeclarativemodels.html

    如果你检查样品包括 class Animal {...} 您将看到必须为要提供的不同字段定义角色。并且至少必须定义data()函数,返回给定索引的相应字段值。此外,您可能还需要自己的自定义方法来插入和删除。希望这有帮助…

        3
  •  0
  •   Curtwagner1984    8 年前

    如果有人在寻找答案,我做了一个小应用,它连接到一个具有qAbstractListModel子类的参与者数据库,并根据@fgungor posted的示例在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
    

    B.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()
    

    主.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
                    }
    
    
            }
        }
    }