2

First of all, I am aware that a similar question has been posted here on Stack Overflow. I have tried this solution, however, with no success. Here is a minimum verifiable example of my code:

from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine
from PySide2.QtCore import QObject, Signal, Slot
 
 
class Dictionary(QObject):
    def __init__(self):
        QObject.__init__(self)
        self.dictionary = {1: "Word1", 2: "Word2"}

    sendDict = Signal(dict)
    
    @Slot(bool)
    def s_dict(self, arg1):
        self.sendDict.emit(self.dictionary)

if __name__ == "__main__":
    import sys
 
    app = QGuiApplication(sys.argv)
    engine = QQmlApplicationEngine()
    dictionary = Dictionary()
    engine.rootContext().setContextProperty("dictionary", dictionary)
    engine.load("main.qml")
 
    engine.quit.connect(app.quit)
    sys.exit(app.exec_()) 

And here is the QML file:

import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.2
 
ApplicationWindow {
    visible: true
    width: 640
    height: 240
    title: qsTr("Minimum Verifiable Example")
    color: "whitesmoke"
 
    GridLayout {
        anchors.top: parent.top
        anchors.left: parent.left
        anchors.right: parent.right
        anchors.margins: 9
 
        columns: 4
        rows: 4
        rowSpacing: 10
        columnSpacing: 10
 
        Button {
            height: 40
            Layout.fillWidth: true
            text: qsTr("Emit dictionary!")
 
            Layout.columnSpan: 2
 
            onClicked: {
                dictionary.s_dict(true)
            }
        }
    }

 
    Connections {
        target: dictionary
        function onSendDict(arg1) {console.log(arg1)}
    }
}

To put it simply, I want to print the elements of this dictionary with console.log, however all I get is this: qml: QVariant(PySide::PyObjectWrapper, ). I've tried indexing it as well, but to no avail (it returns undefined).

Thanks for your time!

Raphael Sauer
  • 630
  • 1
  • 6
  • 27

1 Answers1

1

Here's working code that addresses two issues:

  1. The Signal needs to be spec'd with "QVariantMap" for pyside to marshall it into QML as an object correctly.

  2. Object keys in Javascript are always strings so the marshaling appears to be skipping your integer keys. Use strings instead.

from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine
from PySide2.QtCore import QObject, Signal, Slot
 
 
class Dictionary(QObject):
    def __init__(self):
        QObject.__init__(self)
        self.dictionary = {"1": "Word1", "2": "Word2"}

    sendDict = Signal("QVariantMap")
    
    @Slot(bool)
    def s_dict(self, arg1):
        self.sendDict.emit(self.dictionary)

if __name__ == "__main__":
    import sys
 
    app = QGuiApplication(sys.argv)
    engine = QQmlApplicationEngine()
    dictionary = Dictionary()
    engine.rootContext().setContextProperty("dictionary", dictionary)
    engine.load("main.qml")
 
    engine.quit.connect(app.quit)
    sys.exit(app.exec_()) 

and

import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.2
 
ApplicationWindow {
    visible: true
    width: 640
    height: 240
    title: qsTr("Minimum Verifiable Example")
    color: "whitesmoke"
 
    GridLayout {
        anchors.top: parent.top
        anchors.left: parent.left
        anchors.right: parent.right
        anchors.margins: 9
 
        columns: 4
        rows: 4
        rowSpacing: 10
        columnSpacing: 10
 
        Button {
            height: 40
            Layout.fillWidth: true
            text: qsTr("Emit dictionary!")
 
            Layout.columnSpan: 2
 
            onClicked: {
                dictionary.s_dict(true)
            }
        }
    }

 
    Connections {
        target: dictionary
        function onSendDict(arg1) {
            console.log(arg1);
            console.log(JSON.stringify(arg1, null, 4));
        }
    }
}

Output:

qml: [object Object]
qml: {
    "1": "Word1",
    "2": "Word2"
}

You could also use JSON and encode your Python data structures into a string, pass the string to QML and use JSON.parse in Javascript to decode it. That might work better with more complicated data structures.

David K. Hess
  • 16,632
  • 2
  • 49
  • 73