<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>