Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Insert into ListView with Loader
QtWS25 Last Chance

Insert into ListView with Loader

Scheduled Pinned Locked Moved Solved QML and Qt Quick
qmlloaderlistviewpyside2
2 Posts 1 Posters 718 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • O Offline
    O Offline
    oscarthorn
    wrote on 6 Oct 2019, 09:17 last edited by oscarthorn 10 Jun 2019, 09:23
    #1

    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.
    test.qml

    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
                        break;
                    case 'blue':
                        return blue
                        break;
                    case 'green':
                        return green
                        break;
                }
            }
        }
        Component {
            id:red
            Rectangle {
                width: 100
                height: 100
                color: 'red'
            }
        }
        Component {
            id:blue
            Rectangle {
                width: 100
                height: 100
                color: 'blue'
            }
        }
        Component {
            id:green
            Rectangle {
                width: 100
                height: 100
                color: 'green'
            }
        }
    }
    

    test.py

    
    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))
            self.endInsertRows()
    
    
    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
    
    
        @Slot()
        def append(self, name):
            self.model.appendRow('a')
    
    
    def insert_brg(model):
        model.appendRow('blue')
        model.appendRow('red')
        model.appendRow('green')
        model.appendRow('green')
    
    def green(model):
        model.appendRow('green')
    
    if __name__ == '__main__':
        app = QGuiApplication(sys.argv)
    
        provider = ModelProvider()
        engine = QQmlApplicationEngine()
    
        engine.rootContext().setContextProperty("provider", provider)
        engine.load('test.qml')
        if not engine.rootObjects():
            sys.exit(-1)
    
        insert_brg(provider.model)
        timer = QtCore.QTimer(interval=500)
        timer.timeout.connect(partial(green, provider.model))
        timer.start()
    
        sys.exit(app.exec_())
    
    1 Reply Last reply
    0
    • O Offline
      O Offline
      oscarthorn
      wrote on 7 Oct 2019, 07:36 last edited by
      #2

      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.

      1 Reply Last reply
      2

      1/2

      6 Oct 2019, 09:17

      • Login

      • Login or register to search.
      1 out of 2
      • First post
        1/2
        Last post
      0
      • Categories
      • Recent
      • Tags
      • Popular
      • Users
      • Groups
      • Search
      • Get Qt Extensions
      • Unsolved