Python 是否可以通过QML从PySide2插槽(服务调用)获取对象列表?

Python 是否可以通过QML从PySide2插槽(服务调用)获取对象列表?,python,python-3.x,qml,pyside2,Python,Python 3.x,Qml,Pyside2,我正在尝试将现有的PySide2/QtWidgets应用程序转换为PySide2/QML。我试图通过QMLMouseAreaclick从Python服务调用中获取自定义对象的列表 我目前有一个主脚本(main.py),它启动一个包含我的QML(包含在main.QML中)的QQuickView)。它还为我的模型注册自定义类型(Role,在Role.py中定义),并将我的服务类的实例(包含在mock\u Role\u service.py中)公开到视图的根上下文中 我的QML显示正确,我可以单击我的

我正在尝试将现有的PySide2/QtWidgets应用程序转换为PySide2/QML。我试图通过QML
MouseArea
click从Python服务调用中获取自定义对象的列表

我目前有一个主脚本(
main.py
),它启动一个包含我的QML(包含在
main.QML
中)的
QQuickView
)。它还为我的模型注册自定义类型(
Role
,在
Role.py
中定义),并将我的服务类的实例(包含在
mock\u Role\u service.py
中)公开到视图的根上下文中

我的QML显示正确,我可以单击我的
MouseArea
,但我没有返回
List[Role]
,而是得到了一个
QVariant
元组。更具体地说,
QVariant(PySide::PyObjectWrapper,)

相关文件:
mock\u role\u service.py

...
MouseArea {
    onClicked: {
        console.log(roleService.find_all())
        for (role in roleService.find_all()) {
            console.log(role.get_id())
        }
    }
}
...
class MockRoleService(QObject):
定义初始化(自):
super()。\uuuu init\uuuuu()
self.next_id=5
自我记录={
1:角色(id=1,
name='Admin'),
2:角色(id_u2;=2,
name='User')
}
@插槽(结果=列表)
def find_all(self)->列表[角色]:
返回列表(self.records.values())
main.py

。。。
app=qgui应用程序(sys.argv)
qmlRegisterType(角色,'Models',1,0,'Role')
视图=QQuickView()
url=QUrl('Views/main.qml')
view.setSource(url)
view.setResizeMode(QQuickView.SizerootObject视图)
role\u service=mockroleseservice()
view.rootContext().setContextProperty(“roleService”,role\u服务)
如果view.status()==QQuickView.Error:
系统出口(-1)
view.show()
sys.exit(app.exec_())
main.qml

...
MouseArea {
    onClicked: {
        console.log(roleService.find_all())
        for (role in roleService.find_all()) {
            console.log(role.get_id())
        }
    }
}
...
第一个
console.log()
调用的结果是
QVariant(PySide::PyObjectWrapper,)
并且永远不会输入for循环

我只能在网上找到几个类似的问题,到目前为止,解决这些问题的常见方法(如答案中所示)是将值设置为类的属性,并将其指定为
QVariantList
类型。这是因为PySide2显然去掉了它们的类
QVariant
,所以我无法正确指定插槽的结果类型


但是,我不确定这个解决方案是否适合这种情况,因为我正在处理一个服务对象。在服务类上设置属性以保存返回值感觉很脆弱。没有其他方法可以做到这一点吗?

由于您没有提供角色类,我将假定它是一个QObject,如果不是,那么您必须修改您的类,使其不被QML识别,除了在QML中识别信号、QProperty和插槽之外

另一方面,qmlRegisterType仅在您希望在注册类的QML中创建对象时才是必需的,在您的情况下,我认为没有必要这样做

最后,如果要将列表传递给QML,则必须使用签名
“QVariantList”
(如果列表有效,则在PyQt中)

输入导入列表中的

来自PySide2.QtCore导入属性、QObject、QUrl、信号、插槽
从PySide2.QtGui导入qgui应用程序
从PySide2.QtQml导入qmlRegisterType
从PySide2.QtQuick导入QQuickView
类角色(QObject):
idChanged=信号()
名称更改=信号()
定义初始化(self,id,name,parent=None):
super()。\uuuu init\uuuu(父级)
self.\u id=id_
self.\u name=name
def get_id(自身)->int:
返回自我。\u id
def set_id(自身,id)->无:
如果是self.\u id!=身份证号码:
self.\u id=id_
self.idChanged.emit()
def get_名称(自身)->str:
返回self.\u name
def set_名称(self,name)->无:
如果是self.\u name!=姓名:
self.\u name=name
self.nameChanged.emit()
id=属性(int,fget=get\u id,fset=set\u id,notify=idChanged)
name=属性(str,fget=get\u name,fset=set\u name,notify=nameChanged)
类MockRoleService(QObject):
def uuu init uuu(self,parent=None):
super()。\uuuu init\uuuu(父级)
自我记录={
1:角色(id_u2;=1,name=“Admin”,parent=self),
2:角色(id_u2;=2,name=“User”,parent=self),
}
@插槽(结果=“QVariantList”)
def find_all(self)->列表[角色]:
返回列表(self.records.values())
如果名称=“\uuuuu main\uuuuuuuu”:
导入操作系统
导入系统
app=qgui应用程序(sys.argv)
#qmlRegisterType(角色,“模型”,1,0,“角色”)
视图=QQuickView()
current_dir=os.path.dirname(os.path.realpath(uu文件_uu))
url=QUrl.fromLocalFile(os.path.join(当前目录,“Views/main.qml”))
view.setSource(url)
view.setResizeMode(QQuickView.SizerootObject视图)
role\u service=mockroleseservice()
view.rootContext().setContextProperty(“roleService”,role\u服务)
如果view.status()==QQuickView.Error:
系统出口(-1)
view.show()
sys.exit(app.exec_())
输出:

qml: [Role(0x55b5385589b0),Role(0x55b538558d40)]
qml: 1 Admin
qml: 2 User

这正是我需要的,谢谢!您认为角色是QoObject的假设是正确的。为了简洁起见,我省略了它,没有意识到这是让它发挥作用的一个重要部分。