Insert into ListView with Loader

  • Hi!
    I'm a newbie to QML and have encountered some strange behaviour (at least to me).

    I have a ListView with a Loader as a delegate. The Loader loads component using a switch statement based on a name role in the model (the model is a sub-class of QAbstractListModel). So far so good. I can insert new items at the end of the list and they show up using the correct component definition. I can also remove elements and everything works fine. However if I try to insert a element before the last element the component gets created using the wrong component definition, it becomes the same as the last element (except when inserting the first elements, which is very strange).

    Minimal example that always inserts before the last element. The rows that were inserted before app start work, but the rows inserted with the timer all become blue.

    import QtQuick 2.11
    import QtQuick.Window 2.2
    import QtQuick.Controls 2.2
    ApplicationWindow {
        visible: true
        width: 640
        height: 480
        ListView {
            model: provider.model
            anchors.fill: parent
            delegate: Loader {
                width: parent.width
                sourceComponent: switch(NameRole){
                    case 'red':
                        return red
                    case 'blue':
                        return blue
                    case 'green':
                        return green
        Component {
            Rectangle {
                width: 100
                height: 100
                color: 'red'
        Component {
            Rectangle {
                width: 100
                height: 100
                color: 'blue'
        Component {
            Rectangle {
                width: 100
                height: 100
                color: 'green'

    import sys
    from functools import partial
    from PySide2.QtGui import QGuiApplication
    from PySide2.QtCore import Slot, QObject, Property, QAbstractListModel
    from PySide2 import QtCore
    from PySide2.QtQml import QQmlApplicationEngine
    class RuleModel(QAbstractListModel):
        NameRole = QtCore.Qt.UserRole + 1001
        def __init__(self, parent=None):
            super(RuleModel, self).__init__(parent)
            self._entries = []
        def rowCount(self, parent=QtCore.QModelIndex()):
            if parent.isValid(): return 0
            return len(self._entries)
        def data(self, index, role=QtCore.Qt.DisplayRole):
            if 0 <= index.row() < self.rowCount() and index.isValid():
                item = self._entries[index.row()]
                if role == RuleModel.NameRole:
                    return item['NameRole']
        def roleNames(self):
            roles = dict()
            roles[RuleModel.NameRole] = b'NameRole'
            return roles
        def appendRow(self, name):
            self.beginInsertRows(QtCore.QModelIndex(), self.rowCount(), self.rowCount())
            self._entries.insert(self.rowCount()-1, dict(NameRole=name))
    class ModelProvider(QObject):
        def __init__(self, parent=None):
            super(ModelProvider, self).__init__(parent)
            self._model = RuleModel()
        @Property(QObject, constant=False)
        def model(self):
            return self._model
        def append(self, name):
    def insert_brg(model):
    def green(model):
    if __name__ == '__main__':
        app = QGuiApplication(sys.argv)
        provider = ModelProvider()
        engine = QQmlApplicationEngine()
        engine.rootContext().setContextProperty("provider", provider)
        if not engine.rootObjects():
        timer = QtCore.QTimer(interval=500)
        timer.timeout.connect(partial(green, provider.model))

  • Ah, I found the problem. I was telling beginInserRows I was going to insert at the end and then not inserting at the end. Telling it the right place solved the problem.

  • Ah, I found the problem. I was telling beginInserRows I was going to insert at the end and then not inserting at the end. Telling it the right place solved the problem.