Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

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 this

    Also, 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
        }
    }
    

    Screenshot_20210212_234631.png

    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 and delagate



  • 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
        }
    }
    

    Screenshot_20210212_234631.png

    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.




Log in to reply