Problem with custom ListView model and a custom item
-
Hi,
I'm trying to create a custom ListView model, that each item has 3 properties, qml sees the correct number of items in the model and I can print each property value with Component.onCompleted: print(backend.model[0].property_name) but nothing is displayed in the ListView and I get "cannot assign [undefined] to QString" (same with QColor).main.py import sys import os from PySide6.QtCore import QObject, Property from PySide6.QtGui import QGuiApplication from PySide6.QtQml import QQmlApplicationEngine class ItemModel(QObject): def __init__(self, value1, value2): QObject.__init__(self) self._text_value = value1 self._color_value = value2 @Property(str) def text_value(self): return self._text_value @Property(str) def color_value(self): return self._color_value class ListModel(QObject): def __init__(self): QObject.__init__(self) self.list_of_items = [] def add_item(self, value1, value2): item = ItemModel(value1, value2) self.list_of_items.append(item) @Property("QVariantList", constant=True) def model(self): return self.list_of_items class MainWindow(QObject): def __init__(self): QObject.__init__(self) self._model = ListModel() self.test_items() def test_items(self): self._model.add_item("First Item", "Green") self._model.add_item("Second Item", "Yellow") @Property("QVariantList", constant=True) def model(self): return self._model.model main = MainWindow() app = QGuiApplication(sys.argv) engine = QQmlApplicationEngine() engine.rootContext().setContextProperty("backend", main) cur_dir = os.path.dirname(__file__) engine.load(os.path.join(cur_dir, "main.qml")) if not engine.rootObjects(): sys.exit(-1) running = app.exec_() sys.exit(running)
main.qml import QtQuick import QtQuick.Controls ApplicationWindow { id: root width: 200 height: 300 visible: true title: "test" Component { id: delegateModel Text {text: model.text_value; color: model.color_value} } ListView { id: itemsListView anchors.fill: parent model: backend.model delegate: delegateModel } Connections { target: backend } Component.onCompleted: { print("1) text:"+backend.model[0].text_value+", color:"+backend.model[0].color_value) print("2) text:"+backend.model[1].text_value+", color:"+backend.model[1].color_value) } }
From my understanding @Property(str) should have defined it for qml, but I'm kinda lost as to why this doesn't display.
What am I missing? or not understanding properly? I also tried using QObject instead of QVariantList but got the same result.
Not sure if it's relevant but I'm using PySide6 for thisAlso, would this approach allow me to update the model just by appending items to self.list_of_items? Or would I need to use a signal?
Thanks in advance
-
@Tauri If the model is a list then to access each element then you must use "modelData" which in your case will be an "ItemModel", and then you can access the qproperties:
import QtQuick import QtQuick.Controls ApplicationWindow { id: root width: 200 height: 300 visible: true title: "test" Component { id: delegateModel Text { text: model.modelData.text_value color: model.modelData.color_value } } ListView { id: itemsListView anchors.fill: parent model: backend.model delegate: delegateModel } }
Note: as expected, it was necessary that you provide an MRE to understand the cause of the error.
-
Could you provide a minimum reproducible code? where you include the imports as well as how you add elements to the model and export it. Maybe in those parts this is the error in addition to that it would help us to test your code in a simple way. So please edit your post and add that information
In addition, it also corrects the TYPOS such as:
modelDelagte
anddelagate
-
Hey @eyllanesc,
Thanks for the response, I updated the post with some minimal code that produces the same errors for me and corrected the typos you mentioned.
-
@Tauri If the model is a list then to access each element then you must use "modelData" which in your case will be an "ItemModel", and then you can access the qproperties:
import QtQuick import QtQuick.Controls ApplicationWindow { id: root width: 200 height: 300 visible: true title: "test" Component { id: delegateModel Text { text: model.modelData.text_value color: model.modelData.color_value } } ListView { id: itemsListView anchors.fill: parent model: backend.model delegate: delegateModel } }
Note: as expected, it was necessary that you provide an MRE to understand the cause of the error.
-
Thanks @eyllanesc! Works like a charm now.
Is there a good learning source you can recommend for stuff like that? specifically having python as a backend to qml.
Maybe I'm missing it but all I found in the docs are either qml with c++ examples, or just using purely pyside without working with python models/objects in qml directly.