如何使用信号将 python 字典发送到 QML 接口?
How can I send a python dictionary to a QML interface with a Signal?
我想发送字典,其中包含我需要用来动态创建 qml 对象的数据,从 PySide2 class 到 QML 接口,因为我需要这样做以响应某些事件,我需要使用信号和槽。
因为我刚开始使用 QML 和 python 我尝试创建一个简单的项目来玩一下(正如您从代码中看到的那样)
QML:
import QtQuick 2.10
import QtQuick.Controls 2.2
import QtQuick.Window 2.2
import QtQuick.Controls.Material 2.3
import QtQuick.Layouts 1.0
ApplicationWindow {
id: mainWindow
width:640
height: 480
title: qsTr("Simple ui")
visible: true
locale:locale
Rectangle {
id: appWindow
objectName: "splasso"
anchors.fill: parent
color: "yellow"
Material.accent: Material.DeepPurple
Material.primary: Material.Cyan
Component.onCompleted: function(){
TestVar.theSignal.connect(catchAnswer);
testList.append(stuff1);
testList.append(stuff2);
testList.append(stuff3);
testCombo.currentIndex = 0;
//Just a pointless test print
console.log(JSON.stringify(stuff1));
}
function catchAnswer(answer){
console.log(JSON.stringify(answer));
}
ComboBox{
id: testCombo
anchors.centerIn: parent
width: parent.width
onCurrentIndexChanged: function(){
TestVar.catchInt(currentIndex);
}
model: ListModel{
id: testList
}
}
}
}
Python 3:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
import os
from time import sleep
from PySide2.QtCore import Qt, QObject, Signal, Slot, Property, QThread
from PySide2.QtWidgets import QApplication
from PySide2.QtQml import QQmlApplicationEngine
class Test1(QObject):
theSignal = Signal(dict)
def __init__(self):
QObject.__init__(self)
@Slot(int)
def catchInt(self,caught):
print("Caught: {0}".format(caught))
testDict = {"myAnswer":caught}
self.theSignal.emit(testDict)
if __name__ == "__main__":
os.environ["QT_QUICK_CONTROLS_STYLE"] = "Material"
app = QApplication(sys.argv)
engine = QQmlApplicationEngine()
stuff1 = {"text":"Trying"}
stuff2 = {"text":"To send"}
stuff3 = {"text":"Dict"}
ctx = engine.rootContext()
ctxVar = Test1()
ctx.setContextProperty("stuff1", stuff1)
ctx.setContextProperty("stuff2", stuff2)
ctx.setContextProperty("stuff3", stuff3)
ctx.setContextProperty("TestVar",ctxVar)
engine.load('main.qml')
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec_())
我预期的输出(使用 "python3 Test_dict_1.py" 启动脚本)是:
Caught: 1
qml: {"myAnswer": 1}
Caught: 2
qml: {"myAnswer": 2}
Caught: 1
qml: {"myAnswer": 1}
...etc...
我得到的是:
Caught: 1
qml: undefined.
Caught: 2
qml: undefined.
Caught: 1
qml: undefined.
...etc...
你能告诉我我做错了什么吗?是代码有错误还是这东西做不出来?
您必须在信号中使用的签名是 QVariant
:
class Test1(QObject):
theSignal = Signal('QVariant')
@Slot(int)
def catchInt(self,caught):
print("Caught: {0}".format(caught))
testDict = {"myAnswer":caught}
self.theSignal.emit(testDict)
我想发送字典,其中包含我需要用来动态创建 qml 对象的数据,从 PySide2 class 到 QML 接口,因为我需要这样做以响应某些事件,我需要使用信号和槽。
因为我刚开始使用 QML 和 python 我尝试创建一个简单的项目来玩一下(正如您从代码中看到的那样)
QML:
import QtQuick 2.10
import QtQuick.Controls 2.2
import QtQuick.Window 2.2
import QtQuick.Controls.Material 2.3
import QtQuick.Layouts 1.0
ApplicationWindow {
id: mainWindow
width:640
height: 480
title: qsTr("Simple ui")
visible: true
locale:locale
Rectangle {
id: appWindow
objectName: "splasso"
anchors.fill: parent
color: "yellow"
Material.accent: Material.DeepPurple
Material.primary: Material.Cyan
Component.onCompleted: function(){
TestVar.theSignal.connect(catchAnswer);
testList.append(stuff1);
testList.append(stuff2);
testList.append(stuff3);
testCombo.currentIndex = 0;
//Just a pointless test print
console.log(JSON.stringify(stuff1));
}
function catchAnswer(answer){
console.log(JSON.stringify(answer));
}
ComboBox{
id: testCombo
anchors.centerIn: parent
width: parent.width
onCurrentIndexChanged: function(){
TestVar.catchInt(currentIndex);
}
model: ListModel{
id: testList
}
}
}
}
Python 3:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
import os
from time import sleep
from PySide2.QtCore import Qt, QObject, Signal, Slot, Property, QThread
from PySide2.QtWidgets import QApplication
from PySide2.QtQml import QQmlApplicationEngine
class Test1(QObject):
theSignal = Signal(dict)
def __init__(self):
QObject.__init__(self)
@Slot(int)
def catchInt(self,caught):
print("Caught: {0}".format(caught))
testDict = {"myAnswer":caught}
self.theSignal.emit(testDict)
if __name__ == "__main__":
os.environ["QT_QUICK_CONTROLS_STYLE"] = "Material"
app = QApplication(sys.argv)
engine = QQmlApplicationEngine()
stuff1 = {"text":"Trying"}
stuff2 = {"text":"To send"}
stuff3 = {"text":"Dict"}
ctx = engine.rootContext()
ctxVar = Test1()
ctx.setContextProperty("stuff1", stuff1)
ctx.setContextProperty("stuff2", stuff2)
ctx.setContextProperty("stuff3", stuff3)
ctx.setContextProperty("TestVar",ctxVar)
engine.load('main.qml')
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec_())
我预期的输出(使用 "python3 Test_dict_1.py" 启动脚本)是:
Caught: 1
qml: {"myAnswer": 1}
Caught: 2
qml: {"myAnswer": 2}
Caught: 1
qml: {"myAnswer": 1}
...etc...
我得到的是:
Caught: 1
qml: undefined.
Caught: 2
qml: undefined.
Caught: 1
qml: undefined.
...etc...
你能告诉我我做错了什么吗?是代码有错误还是这东西做不出来?
您必须在信号中使用的签名是 QVariant
:
class Test1(QObject):
theSignal = Signal('QVariant')
@Slot(int)
def catchInt(self,caught):
print("Caught: {0}".format(caught))
testDict = {"myAnswer":caught}
self.theSignal.emit(testDict)