Yo jugueteaba con la creación de subclases QAbstractListModel, y no creo que entender la forma correcta de agregar datos al modelo. Aquí está mi script y el 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()
Mi expectativa es que, cada vez que el temporizador de tiempo de espera, una nueva fila se añade a la listmodel, y por lo tanto, la listmodel del dataChanged
la señal debe conseguir que se emite. El Connections
objeto de la señal del controlador debe imprimir un mensaje. Pero parece que nunca se ejecuta:
$ python example.py
qml: Component completed
Adding 7 and 0
Adding 8 and 5
Adding 4 and 0
...
Si puedo agregar explícitamente self.dataChanged.emit()
después de endInsertRows()
, entonces, obviamente, el manejador se ejecuta. Pero en toda la documentación y código de ejemplo que veo, no lo hace. Así que, ¿cuál es el enfoque adecuado?