[PyQt] PyQt5.8.2 Qml GridView TypeError: unable to convert a Python 'MyListModel' object to a C++ 'QAbstractListModel*' instance

chunyisong at sina.com chunyisong at sina.com
Mon Apr 3 02:46:03 BST 2017



Hello everyone,


I encountered an “TypeError” that my python subclass listmodel of QAbsctactListModel object can not be recognized as a  C++ 'QAbstractListModel*' instance!
In order to simplify the problem, I simplified the project code to a demo attachments and also listed below the contents of the email.
The demo has two python subclass of QAbsctactListModel :RuleModel and RuleGroupModel;RuleModel instance will be a role of RuleGroupModel 
 to provide rules of a group.I test it with PyQt5.7.1 and PyQt5.8.2 ,both encountered the same Type Error which crashed the app is:
        " TypeError: invalid result from RuleGroupModel.data(), unable to convert a Python 'RuleModel' object to a C++ 'QAbstractListModel*' instance ".
But  when the count of changing model of Qml GridView "many times" ,the error raised.I am confused thar the error do not occure within a few times such as 5 or more times;
The error will surely occure after more times of rule model change.To reproduce the error I use a Timer in the Test.qml to simulate many times of user actions.
Any advice to the e
Thanks in advance!


The demo code:
#### testmodel.py#######################
#encoding:utf8
'''
file:testmodel.py
'''
# import cgitb
# cgitb.enable()
import sys

from PyQt5.QtCore import QUrl, QAbstractListModel,QModelIndex,pyqtSlot
from PyQt5 import QtQml
from PyQt5.QtGui import QGuiApplication
from PyQt5.QtQuick import QQuickView

class RuleModel(QAbstractListModel):
    def __init__(self,name=2,parent=None):
        super().__init__(parent)
        self._datas = [{"name":"name %s" % k} for k in range(name)]
    def setDS(self,ds):
        self._datas = ds
    def roleNames(self):
        return {300:"name".encode()}
    def data(self,index,role=500):
        return self._datas[index.row()][self.roleNames().get(role).decode()]
    def rowCount(self,parent=QModelIndex()):
        return len(self._datas)

class RuleGroupModel(QAbstractListModel):
    def __init__(self,parent=None):
        super().__init__(parent)
        self._datas = [{"name":"na1" ,"rulesModel":RuleModel(name=1)},
            {"name":"na2" ,"rulesModel":RuleModel(name=2)},
            {"name":"na3" ,"rulesModel":RuleModel(name=3)},
            {"name":"na4" ,"rulesModel":RuleModel(name=4)}
        ]
    def setDS(self,ds):
        self._datas = ds
    @pyqtSlot(str,result=int)
    def roleValue(self, roleName):
        if roleName == 'name':
            return 300
        elif roleName == 'rulesModel':
            return 500
        return -1
    def roleNames(self):
        return {300:"name".encode(),500:"rulesModel".encode()}
    def data(self,index,role=500):
        return self._datas[index.row()][self.roleNames().get(role).decode()]
    def rowCount(self,parent=QModelIndex()):
        return len(self._datas)
    
    
if __name__ == '__main__':

    
    app = QGuiApplication(sys.argv)

    view = QQuickView()
    
    engine = view.engine()
    engine.quit.connect(app.quit)
    
    modelA = RuleGroupModel()
    engine.rootContext().setContextProperty('ruleGroupsModel', modelA)


    view.setResizeMode(QQuickView.SizeRootObjectToView)
    QtQml.qmlRegisterType(RuleGroupModel, 'RuleGroupModel', 1, 0, 'RuleGroupModel')
    QtQml.qmlRegisterType(RuleMode
l, 'RuleModel', 1, 0, 'RuleModel')

    view.setSource(QUrl('Test.qml'))
    view.show()

    sys.exit(app.exec_())
#### end of testmodel.py#######################
#### Test.qml #######################

importQtQuick2.7
importQtQuick.Controls2.0
importQtQuick.Layouts1.0


Page{
width:300
height:600
header:ComboBox{
id:groups


currentIndex:-1
displayText:currentIndex==-1?"selectagroup":currentText
model:ruleGroupsModel
textRole:"name"


onCurrentIndexChanged:{
rulesView.model=model.data(model.index(currentIndex,0),
model.roleValue('rulesModel'))
}
}


Timer{
id:timer
interval:1000
repeat:true
running:false
propertyintcount:0
onTriggered:{
count+=1
varidx=count%groups.model.rowCount()
console.log('timertrigger',idx,count)
groups.currentIndex=idx
}
}


Component{
id:ruleDelegate
RowLayout{


id:ruleName
width:300
height:40


Label{
verticalAlignment:Text.AlignVCenter
horizontalAlignment:Text.AlignHCenter
text:["<b>",model.name,"<b>"].join('')
Layout.fillWidth:true
Layout.preferredWidth:3
}
}
}
GridView{
id:rulesView


anchors.fill:parent


cellHeight:50
cellWidth:220


delegate:ruleDelegate
}
Component.onCompleted:{
timer.running=true
console.log('mainload',ruleGroupsModel)
}
}
####### end of Test.qml ############


Thanks !
--

songchunyi




 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20170403/488ddd6c/attachment-0001.html>
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: Test.qml
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20170403/488ddd6c/attachment-0001.ksh>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: testmodel.py
Type: application/octet-stream
Size: 2275 bytes
Desc: not available
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20170403/488ddd6c/attachment-0001.obj>


More information about the PyQt mailing list