I created a PySide6 QML project where a QmlElement
class has a slot function callable from the QML interface. After invoking this slot, the class instance asynchronously emits a signal to send a text to a QML control, but unexpectedly receives an object instead. How can I resolve this issue?
@QmlElement
I defined:import sys
from argparse import ArgumentParser
from pathlib import Path
from PySide6.QtCore import QObject, Signal, Slot, Property
from PySide6.QtGui import QGuiApplication
from PySide6.QtQml import QmlElement, QQmlApplicationEngine, QQmlDebuggingEnabler
QML_IMPORT_NAME = "my.ext"
QML_IMPORT_MAJOR_VERSION = 1
@QmlElement
class MyClass(QObject):
valueChanged = Signal(str)
@Slot()
def setText(self):
self.valueChanged.emit('str')
if __name__ == '__main__':
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
engine.addImportPath(Path(__file__).parent)
qml_file = Path(__file__).parent / 'main.qml'
engine.load(qml_file)
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec())
import QtQuick
import QtQuick.Controls
import my.ext
ApplicationWindow {
id: appWindow
width: 800
height: 600
visible: true
title: "Application"
Text {
id: text
anchors.centerIn: parent
text: "Hello World!"
}
MouseArea {
anchors.fill: parent
onClicked: {
myObj.setText()
}
}
MyClass {
id: myObj
onValueChanged: {
text.text = '' + data
console.log("Value changed: " + data)
}
}
}
run: shows "Hello World"
after click, it shows:
QQuickItem(0x1f5169ed150),QQuickContentItem(0x1f5169ed6c0, "ApplicationWindow")
You are assuming that "data" is the object being sent via the signal. data is a property of ApplicationWindow:
data : list<Object>
The data property allows you to freely mix visual children, resources and other Windows in a Window.
If you assign another Window to the data list, the nested window will become "transient for" the outer Window.
If you assign an Item to the data list, it becomes a child of the Window's contentItem, so that it appears inside the window. The item's parent will be the window's contentItem, which is the root of the Item ownership tree within that Window.
If you assign any other object type, it is added as a resource.
It should not generally be necessary to refer to the data property, as it is the default property for Window and thus all child items are automatically assigned to this property.
See also QWindow::transientParent().
That's why a list of Objects is printed.
A possible solution is to use arguments to set the name of the object being sent:
valueChanged = Signal(str, arguments=["val"])
Then:
MyClass {
id: myObj
onValueChanged: {
text.text = '' + val
console.log("Value changed: " + val)
}
}