Is it possible to pass init arguments to a python class registered to QML using the qmlRegisterType function? If so, would they be passed when the class is instantiated within QML?
I've registered the class with qmlRegisterType, but don't see a way to pass in another class instance as an object. I do see there is a way to register extension objects, but per the documentation, those can only be properties. I'd like to pass in another instantiated class so that I can access its methods and properties within the class I am registering to QML.
How the class would be instantiated in Python:
from PySide2.QtWidgets import QApplication
from PySide2.QtQml import QQmlApplicationEngine, qmlRegisterType, QQmlComponent
from PySide2.QtCore import QObject
from app import Sites
from models import RoutesConn
def main():
# create the application instance
app = QApplication(sys.argv)
# create a QML engine
engine = QQmlApplicationEngine()
# instantiate Sites instance
sites = Sites()
# instantiate RoutesConn instance, and pass in sites instance
routesconn = RoutesConn(sites)
# this could be provided to qml as an object
engine.rootContext().setContextProperty('RoutesConn', routesconn)
However, the sites instance can't be passed if registered as a class in qml. I would think the sites class could also be registered to qml and passed to RoutesConn when instantiated in QML, but I haven't seen a way to do that.
Register class to QML in Python:
qmlRegisterType(RoutesConn, 'RoutesConn', 1, 0, 'RoutesConn')
QML:
import RoutesConn 1.0
RoutesConn {
id: rconn
....
}
I would expect there were a way to pass objects into the class during initialization after registration to qml, but that doesn't appear to be the case.
TL; DR; No, it is not possible.
QML expects that the QObjects registered through qmlRegisterType only have a constructor that receives a QObject as parent (qmlRegisterType does not build the object, only makes it available in QML):
class Foo(QtCore.QObject):
def __init__(self, parent=None):
super().__init__(parent)
# ...
If you want to pass other objects you must do it through a Slot or Property:
from PySide2 import QtCore, QtGui, QtQml
class Bar(QtCore.QObject):
def test(self):
print("test")
class Foo(QtCore.QObject):
def __init__(self, parent=None):
super().__init__(parent)
self.m_bar = None
@QtCore.Slot(Bar)
def load_bar(self, bar):
self.m_bar = bar
@QtCore.Slot()
def test_bar(self):
if self.m_bar is not None:
self.m_bar.test()
if __name__ == "__main__":
import os
import sys
app = QtGui.QGuiApplication(sys.argv)
QtQml.qmlRegisterType(Foo, 'TestComponents', 1, 0, 'Foo')
QtQml.qmlRegisterType(Bar, 'TestComponents', 1, 0, 'Bar')
engine = QtQml.QQmlApplicationEngine()
file = os.path.join(os.path.dirname(os.path.realpath(__file__)), "main.qml")
engine.load(file)
if not engine.rootObjects():
sys.exit(-2)
sys.exit(app.exec_())
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Controls 2.5
import TestComponents 1.0
ApplicationWindow {
visible: true
width: 640
height: 480
color: "whitesmoke"
Foo{
id: foo
Component.onCompleted: load_bar(bar)
}
Bar{
id: bar
}
Button {
text: "Cancel"
onClicked: foo.test_bar()
anchors.centerIn: parent
}
}
from PySide2 import QtCore, QtGui, QtQml
class Bar(QtCore.QObject):
def test(self):
print("test")
class Foo(QtCore.QObject):
barChanged = QtCore.Signal()
def __init__(self, parent=None):
super().__init__(parent)
self.m_bar = None
def getBar(self):
return self.m_bar
def setBar(self, bar):
if self.m_bar != bar:
self.m_bar = bar
self.barChanged.emit()
bar = QtCore.Property(Bar, fget=getBar, fset=setBar, notify=barChanged)
@QtCore.Slot()
def test_bar(self):
if self.m_bar is not None:
self.m_bar.test()
if __name__ == "__main__":
import os
import sys
app = QtGui.QGuiApplication(sys.argv)
QtQml.qmlRegisterType(Foo, "TestComponents", 1, 0, "Foo")
QtQml.qmlRegisterType(Bar, "TestComponents", 1, 0, "Bar")
engine = QtQml.QQmlApplicationEngine()
file = os.path.join(os.path.dirname(os.path.realpath(__file__)), "main.qml")
engine.load(file)
if not engine.rootObjects():
sys.exit(-2)
sys.exit(app.exec_())
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Controls 2.5
import TestComponents 1.0
ApplicationWindow {
visible: true
width: 640
height: 480
color: "whitesmoke"
Foo{
id: foo
bar: bar_object
}
Bar{
id: bar_object
}
Button {
text: "Cancel"
onClicked: foo.test_bar()
anchors.centerIn: parent
}
}