PyQt und QML - Wie kann ich ein benutzerdefiniertes Datenmodell erstellen
Frage
Wie soll ich ein QAbstractListModel in PyQt erstellen und verwenden Sie es mit einem QML Listview?
Lösung
Sie müssen es die Rollennamen festlegen zu können, um es in QML verwenden;
http://doc.qt.io/qt-4.8/qabstractitemmodel. html # setRoleNames
Andere Tipps
Haben Sie nicht PyQT verwendet, aber Sie können eine minimale Arbeitsprobe finden Sie hier: http: / /doc.qt.nokia.com/stable/qdeclarativemodels.html
Wenn Sie die Probe einschließlich der class Animal {...}
überprüfen Sie werden sehen, dass Sie Rollen für die verschiedenen Felder definieren, müssen Sie liefern wollen. Und bei einem Minimum müssen Sie die Daten () Funktion Rückgabe des entsprechenden Feldwert für einen gegebenen Index definieren. Auch werden Sie Ihre eigenen Methoden zum Einsetzen und Entfernen benötigen möglicherweise. Hoffe, das hilft ...
Wenn jemand anderes nach einer Antwort suchen, habe ich eine kleine Anwendung, dass eine Verbindung zu einer Datenbank von Akteuren mit einer Unterklasse von QAbstractListModel und zeigt die Thumbnails in QGridView am Beispiel @fgungor gebucht. (PyQt5)
main.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")
models.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
db.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
}
}
}
}