Byl jsem si pohráváte s subclassing QAbstractListModel, a nemyslím si, že bych pochopit, jak správně přidat data do modelu. Tady je můj scénář a QML:
import QtQuick
import QtQuick.Controls
ApplicationWindow
{
id: mainWindow
visible: true
title: qsTr("Sample Qt Quick application")
width: 400
height: 400
color: "whitesmoke"
Component.onCompleted: console.log("Component completed")
Connections
{
target: main.custom_model
function onDataChanged(topLeft, bottomRight, roles)
{
console.log("Custom model data changed")
}
}
} // ApplicationWindow
import sys
from random import randint
from pathlib import Path
from PySide6.QtCore import Qt, QObject, QTimer, Property, QAbstractListModel, QModelIndex
from PySide6.QtGui import QGuiApplication
from PySide6.QtQml import QQmlApplicationEngine
class CustomModel(QAbstractListModel):
def __init__(self, parent=None):
super().__init__(parent)
self._my_items = []
self._role1 = Qt.UserRole + 1
self._role2 = Qt.UserRole + 2
self._roles = {
self._role1: b"role1",
self._role2: b"role2"
}
def append_item(self, arg1, arg2):
row_count = self.rowCount()
self.beginInsertRows(QModelIndex(), row_count, row_count)
self._my_items.append({
self._roles[self._role1]: arg1,
self._roles[self._role2]: arg2
})
self.endInsertRows()
def rowCount(self, parent=QModelIndex()):
"""
Required for subclasses of QAbstractListModels
"""
return len(self._my_items)
def data(self, index, role=Qt.DisplayRole):
"""
Required for subclasses of QAbstractListModels
"""
try:
the_item = self._my_items[index.row()]
except IndexError:
return QVariant()
if role in self._roles:
key = self._roles[role]
return the_item[key]
return QVariant()
def roleNames(self):
return self._roles
class MainContextClass(QObject):
def __init__(self, parent=None):
super().__init__(parent)
self._model = CustomModel()
def add_an_item(self):
thing1 = randint(0, 9)
thing2 = randint(0, 9)
print("Adding {0} and {1}".format(thing1, thing2))
self._model.append_item(thing1, thing2)
@Property(QObject, constant=True)
def custom_model(self):
return self._model
def main():
app = QGuiApplication(sys.argv)
qml_app_engine = QQmlApplicationEngine()
qml_context = qml_app_engine.rootContext()
main_context = MainContextClass(parent=app)
qml_context.setContextProperty("main", main_context)
this_file_path = Path(__file__)
main_qml_path = this_file_path.parent / 'example.qml'
qml_app_engine.load(str(main_qml_path))
timer = QTimer()
timer.setInterval(1000)
timer.setSingleShot(False)
timer.timeout.connect(main_context.add_an_item)
timer.start()
sys.exit(app.exec())
if __name__ == '__main__':
main()
Moje očekávání je, že pokaždé, když časovač vyprší, nový řádek bude přidána do listmodel, a proto je listmodel dataChanged
signál by měl dostat signál. Na Connections
objekt je signál handler by pak vytisknout zprávu. Ale zdá se, jako by se to nikdy spustí:
$ python example.py
qml: Component completed
Adding 7 and 0
Adding 8 and 5
Adding 4 and 0
...
Pokud jsem se explicitně přidat self.dataChanged.emit()
po endInsertRows()
, pak samozřejmě signál handler provádí. Ale ve všech dokumentaci a příklad kódu vidím, to není provedeno. Takže, co je správný přístup?