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. My qml doesn't find my model from python
Forum Update on Monday, May 27th 2025

My qml doesn't find my model from python

Scheduled Pinned Locked Moved Solved QML and Qt Quick
4 Posts 2 Posters 1.5k 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.
  • L Offline
    L Offline
    le-fab.
    wrote on last edited by le-fab.
    #1

    Hello here is a simple test to fill a ListView from ma python main file, I have the following error:
    file:/// ..... /main.qml:26: ReferenceError: elements is not defined

    here is the qml file

    import QtQuick 2.9
    import QtQuick.Window 2.2
    import QtQuick.Controls 1.4
    import PyModels 1.0
    
    Window {
        id: window
        visible: true
        width: 640
        height: 460
        title: qsTr("Test")
        
        Button {
            id: btn
            text: qsTr("fill model")
            onClicked: {
                py_mainapp.fillModel()
            }
        }
    
        ListView {
                anchors.top: parent.top
                anchors.left: btn.right
                anchors.right: parent.right
                anchors.bottom: parent.bottom
                model: elements.items
                delegate: Item {
                    anchors.left: parent.left
                    anchors.right: parent.right
                    height: 24
                    Row {
                        anchors.fill: parent
                        Label {
                            text: model.name
                        }
                        Label {
                            text: model.title
                    }
                }
            }
        }     
        
    }
    

    Here is the py file

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    import sys
    import os
    from PyQt5.QtWidgets import QApplication
    from PyQt5.QtQml import QQmlApplicationEngine, QQmlListProperty, qmlRegisterType
    from PyQt5.QtCore import pyqtSlot, QObject, QVariant,pyqtProperty
    
    
    class ListElementPy(QObject):
    
        def __init__(self, name, title):
            super(ListElementPy, self).__init__()
            self._title = title
            self._name = name
            
        @pyqtProperty('QString')
        def title(self):
            return self._title
    
        @title.setter
        def title(self, avalue):
            if avalue != self._title:
                self._title = avalue
                    
        @pyqtProperty('QString')
        def name(self):
            return self._name
            
        @name.setter
        def name(self, avalue):
            if avalue != self._name:
                self._name = avalue
                    
    
    class ElementsPy(QObject):
        
        def __init__(self):
            super(ElementsPy, self).__init__()
            self._items = []
            
        @pyqtProperty('QString')
        def items(self):
            return QQmlListProperty(ListElementPy, self, self._items)
           
        def append(self, avalue):
            self._items.append(avalue)
                    
    
    class MainApp(QObject):
    
        def __init__(self, context, parent):
            super(MainApp, self).__init__(parent)
            self.win = parent
            self.ctx = context
            self.elements = ElementsPy()
            
    
        @pyqtSlot()
        def fillModel(self):
            for x in range (1,50):
                self.elements.append(ListElementPy("name %.0f" % (x), "title %.0f" % (x)))
                
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        qmlRegisterType(ListElementPy, "PyModels", 1, 0, "ListElementPy")
        qmlRegisterType(ElementsPy, "PyModels", 1, 0, "ElementsPy")
        engine = QQmlApplicationEngine()
        ctx = engine.rootContext()
        engine.load("main.qml")
        win = engine.rootObjects()[0]
        py_mainapp = MainApp(ctx, win)
        ctx.setContextProperty("py_mainapp", py_mainapp)
        ctx.setContextProperty("elements", py_mainapp.elements)
        win.show()
        sys.exit(app.exec_())
    
    

    What am I doing wrong?
    py_mainapp is found in the qml, but not elements

    L 1 Reply Last reply
    0
    • L le-fab.

      Hello here is a simple test to fill a ListView from ma python main file, I have the following error:
      file:/// ..... /main.qml:26: ReferenceError: elements is not defined

      here is the qml file

      import QtQuick 2.9
      import QtQuick.Window 2.2
      import QtQuick.Controls 1.4
      import PyModels 1.0
      
      Window {
          id: window
          visible: true
          width: 640
          height: 460
          title: qsTr("Test")
          
          Button {
              id: btn
              text: qsTr("fill model")
              onClicked: {
                  py_mainapp.fillModel()
              }
          }
      
          ListView {
                  anchors.top: parent.top
                  anchors.left: btn.right
                  anchors.right: parent.right
                  anchors.bottom: parent.bottom
                  model: elements.items
                  delegate: Item {
                      anchors.left: parent.left
                      anchors.right: parent.right
                      height: 24
                      Row {
                          anchors.fill: parent
                          Label {
                              text: model.name
                          }
                          Label {
                              text: model.title
                      }
                  }
              }
          }     
          
      }
      

      Here is the py file

      #!/usr/bin/env python
      # -*- coding: utf-8 -*-
      import sys
      import os
      from PyQt5.QtWidgets import QApplication
      from PyQt5.QtQml import QQmlApplicationEngine, QQmlListProperty, qmlRegisterType
      from PyQt5.QtCore import pyqtSlot, QObject, QVariant,pyqtProperty
      
      
      class ListElementPy(QObject):
      
          def __init__(self, name, title):
              super(ListElementPy, self).__init__()
              self._title = title
              self._name = name
              
          @pyqtProperty('QString')
          def title(self):
              return self._title
      
          @title.setter
          def title(self, avalue):
              if avalue != self._title:
                  self._title = avalue
                      
          @pyqtProperty('QString')
          def name(self):
              return self._name
              
          @name.setter
          def name(self, avalue):
              if avalue != self._name:
                  self._name = avalue
                      
      
      class ElementsPy(QObject):
          
          def __init__(self):
              super(ElementsPy, self).__init__()
              self._items = []
              
          @pyqtProperty('QString')
          def items(self):
              return QQmlListProperty(ListElementPy, self, self._items)
             
          def append(self, avalue):
              self._items.append(avalue)
                      
      
      class MainApp(QObject):
      
          def __init__(self, context, parent):
              super(MainApp, self).__init__(parent)
              self.win = parent
              self.ctx = context
              self.elements = ElementsPy()
              
      
          @pyqtSlot()
          def fillModel(self):
              for x in range (1,50):
                  self.elements.append(ListElementPy("name %.0f" % (x), "title %.0f" % (x)))
                  
      
      if __name__ == "__main__":
          app = QApplication(sys.argv)
          qmlRegisterType(ListElementPy, "PyModels", 1, 0, "ListElementPy")
          qmlRegisterType(ElementsPy, "PyModels", 1, 0, "ElementsPy")
          engine = QQmlApplicationEngine()
          ctx = engine.rootContext()
          engine.load("main.qml")
          win = engine.rootObjects()[0]
          py_mainapp = MainApp(ctx, win)
          ctx.setContextProperty("py_mainapp", py_mainapp)
          ctx.setContextProperty("elements", py_mainapp.elements)
          win.show()
          sys.exit(app.exec_())
      
      

      What am I doing wrong?
      py_mainapp is found in the qml, but not elements

      L Offline
      L Offline
      le-fab.
      wrote on last edited by le-fab.
      #2

      I added the following lines in the qml (which seems to me quite strange as I already defined elements in the python file)

      ElementsPy {
          id: elements
      }
      ListElementPy {
          property string name
          property string title
      }
      

      Now I have the following error:
      TypeError: init() takes 1 positional argument but 2 were given

      1 Reply Last reply
      0
      • L Offline
        L Offline
        le-fab.
        wrote on last edited by le-fab.
        #3

        ok, I've found on internet (https://riverbankcomputing.com/pipermail/pyqt/2017-January/038497.html) a solution working, so I'm gonna start with modifying the following code which works:
        qml:

        import QtQuick 2.9
        import QtQuick.Window 2.2
        import QtQuick.Controls 1.4
        
        import Example 1.0
        
        Window {
            width: 500
            height: 500
            visible: true
        
            ListView {
                anchors.fill: parent
                model: store.channels
                delegate: Item {
                    anchors.left: parent.left
                    anchors.right: parent.right
                    height: 24
                    Row {
                        anchors.fill: parent
                        Label {
                            text: name
                        }
                        Label {
                            text: title
                        }
                    }
                }
            }
        }
        

        python:

        from sys import argv
        from PyQt5.QtWidgets import QApplication
        from PyQt5.QtCore import QObject, QTimer, pyqtProperty, pyqtSignal
        from PyQt5.QtQml import QQmlListProperty, QQmlApplicationEngine, qmlRegisterType
                        
        class Channel(QObject):
        
            nameChanged = pyqtSignal()
            titleChanged = pyqtSignal()
        
            def __init__(self, name='', title='', *args, **kwargs):
                super().__init__(*args, **kwargs)
                self._name = name
                self._title = title
        
            @pyqtProperty('QString', notify=nameChanged)
            def name(self):
                return self._name
        
            @name.setter
            def name(self, name):
                if name != self._name:
                    self._name = name
                    self.nameChanged.emit()
                    
            @pyqtProperty('QString', notify=nameChanged)
            def title(self):
                return self._title
        
            @title.setter
            def title(self, title):
                if title != self._title:
                    self._title = title
                    self.titleChanged.emit()
        
        class Store(QObject):
        
            channelsChanged = pyqtSignal()
        
            def __init__(self, *args, **kwargs):
                super().__init__(*args, **kwargs)
                self._channels = [
                    Channel('aa', 'AAA'),
                    Channel('bb', 'BBB')
                ]
        
            @pyqtProperty(QQmlListProperty, notify=channelsChanged)
            def channels(self):
                return QQmlListProperty(Channel, self, self._channels)
        
            @channels.setter
            def channels(self, channels):
                if channels != self._channels:
                    self._channels = channels
                    self.channelsChanged.emit()
        
            def appendChannel(self, channel):
                self._channels.append(channel)
                self.channelsChanged.emit()
        
        
        def main():
            app = QApplication(argv)
        
            qmlRegisterType(Channel, 'Example', 1, 0, 'Channel')
            qmlRegisterType(Store, 'Example', 1, 0, 'Store')
        
            store = Store()
        
            engine = QQmlApplicationEngine()
            engine.rootContext().setContextProperty('store', store)
            engine.load('main.qml')
        
            # After 3 seconds, we append a new Channel
            QTimer.singleShot(3000, lambda: store.appendChannel(Channel('cc', 'CCC')))
        
            exit(app.exec_())
        
        
        if __name__ == '__main__':
            main()
        
        1 Reply Last reply
        0
        • VRoninV Offline
          VRoninV Offline
          VRonin
          wrote on last edited by VRonin
          #4

          The problem is in your delegate. The syntax is role.property not modelName.property. See this wiki post (the code is C++ but there's no real difference in python)

          "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
          ~Napoleon Bonaparte

          On a crusade to banish setIndexWidget() from the holy land of Qt

          1 Reply Last reply
          1

          • Login

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