<div dir="ltr"><div>Sending basic javascript objects (ie: anything expressible with simple json) down to PyQt works fantastically well with the use of <font face="monospace, monospace">QJSValue.toVariant()</font>, but I'm having a hard time figuring out how to do the reverse.</div><div><br></div><div>What is the correct way to send arbitrarily nested, json-expressible, objects from PyQt up to QML?</div><div><br></div><div>Below is a small example that demonstrates both aspects. Push the button and you can send an arbitrary javascript/json object down to python. It will translate to python perfectly. The example then tries to send it back to QML in a signal argument, but the result isn't quite right.</div><div><br></div><div>Here's the console output for the unmodified example (after button push):</div><div><font color="#674ea7"><br></font></div><div><div><font face="monospace, monospace" color="#674ea7">Python received: [{'foo': 'bar', 'baz': 1}, [1, 2, 3]]</font></div><div><font face="monospace, monospace" color="#674ea7">Emitting signal...</font></div><div><font face="monospace, monospace" color="#674ea7">qml: QML received: [object Object],1,2,3</font></div></div><div><br></div><div>Ideally, QML should receive the same thing!</div><div><br></div><div>I have tried some variations of QJSValue and QVariant with no success. What is the correct way to do this?</div><div><br></div><div>Here is the complete example:</div><div><br></div><div><div><font color="#674ea7" face="monospace, monospace">#!/usr/bin/env python</font></div><div><font color="#674ea7" face="monospace, monospace">import sys</font></div><div><span style="color:rgb(103,78,167);font-family:monospace,monospace">from PyQt5 import QtCore, QtQml, QtQml, QtWidgets</span><br></div><div><font color="#674ea7" face="monospace, monospace"><br></font></div><div><font color="#674ea7" face="monospace, monospace">QML = '''</font></div><div><font color="#674ea7" face="monospace, monospace">import QtQuick 2.5</font></div><div><font color="#674ea7" face="monospace, monospace">import QtQuick.Window 2.2</font></div><div><font color="#674ea7" face="monospace, monospace">import QtQuick.Controls 1.4</font></div><div><font color="#674ea7" face="monospace, monospace">import SignalTesting 1.0</font></div><div><font color="#674ea7" face="monospace, monospace"><br></font></div><div><font color="#674ea7" face="monospace, monospace">Window {</font></div><div><font color="#674ea7" face="monospace, monospace"> id: base</font></div><div><font color="#674ea7" face="monospace, monospace"> visible: true</font></div><div><font color="#674ea7" face="monospace, monospace"> width: 300</font></div><div><font color="#674ea7" face="monospace, monospace"> height: 100</font></div><div><font color="#674ea7" face="monospace, monospace"> </font></div><div><font color="#674ea7" face="monospace, monospace"> SignalTester {</font></div><div><font color="#674ea7" face="monospace, monospace"> id: st</font></div><div><font color="#674ea7" face="monospace, monospace"> onTestSignal: console.log("QML received: " + testVal)</font></div><div><font color="#674ea7" face="monospace, monospace"> }</font></div><div><font color="#674ea7" face="monospace, monospace"> Column {</font></div><div><font color="#674ea7" face="monospace, monospace"> TextInput {</font></div><div><font color="#674ea7" face="monospace, monospace"> id: txtEval</font></div><div><font color="#674ea7" face="monospace, monospace"> text: "[{foo: 'bar', baz: 1}, [1,2,3]]"</font></div><div><font color="#674ea7" face="monospace, monospace"> }</font></div><div><font color="#674ea7" face="monospace, monospace"> Button {</font></div><div><font color="#674ea7" face="monospace, monospace"> text: "sendSignal"</font></div><div><font color="#674ea7" face="monospace, monospace"> onClicked: st.sendSignal(eval(txtEval.text))</font></div><div><font color="#674ea7" face="monospace, monospace"> }</font></div><div><font color="#674ea7" face="monospace, monospace"> }</font></div><div><font color="#674ea7" face="monospace, monospace">}</font></div><div><font color="#674ea7" face="monospace, monospace">'''</font></div><div><font color="#674ea7" face="monospace, monospace"><br></font></div><div><font color="#674ea7" face="monospace, monospace">class SignalTester(QtCore.QObject):</font></div><div><font color="#674ea7" face="monospace, monospace"> testSignal = QtCore.pyqtSignal(QtCore.QVariant, arguments = ["testVal"])</font></div><div><font color="#674ea7" face="monospace, monospace"> </font></div><div><font color="#674ea7" face="monospace, monospace"> @QtCore.pyqtSlot(QtQml.QJSValue)</font></div><div><font color="#674ea7" face="monospace, monospace"> def sendSignal(self, v):</font></div><div><font color="#674ea7" face="monospace, monospace"> v = v.toVariant()</font></div><div><font color="#674ea7" face="monospace, monospace"> print("Python received: %r" % v)</font></div><div><font color="#674ea7" face="monospace, monospace"> print("Emitting signal...")</font></div><div><font color="#674ea7" face="monospace, monospace"> self.testSignal.emit(v)</font></div><div><font color="#674ea7" face="monospace, monospace"><br></font></div><div><font color="#674ea7" face="monospace, monospace"><br></font></div><div><font color="#674ea7" face="monospace, monospace">if __name__ == '__main__':</font></div><div><font color="#674ea7" face="monospace, monospace"> qmlPath = "SignalTester.qml"</font></div><div><font color="#674ea7" face="monospace, monospace"> with open(qmlPath, "w") as fp:</font></div><div><font color="#674ea7" face="monospace, monospace"> fp.write(QML)</font></div><div><font color="#674ea7" face="monospace, monospace"> app = QtWidgets.QApplication(sys.argv + ["-nograb"])</font></div><div><font color="#674ea7" face="monospace, monospace"> QtQml.qmlRegisterType(SignalTester, "SignalTesting", 1, 0, "SignalTester")</font></div><div><font color="#674ea7" face="monospace, monospace"> engine = QtQml.QQmlApplicationEngine(qmlPath)</font></div><div><font color="#674ea7" face="monospace, monospace"> sys.exit(app.exec_())</font></div></div><div><br></div><div><br></div><div><br></div>
</div>