HOWTO access members of a Singleton QML Object type from C++
-
wrote on 9 Nov 2018, 00:25 last edited by
I'm trying to access properties of an "App Settings" QML object from C++. Per various examples, I have made it a singleton, since its only purpose is to provide some settings properties.
I tried to follow the examples here:
http://doc.qt.io/qt-5/qtqml-cppintegration-interactqmlfromcpp.html
to access these properties from C++ via:QQmlComponent component(&engine, QUrl(QStringLiteral("qrc:/AppConfig/Config.qml"))); QObject *object = component.create(); int myWidth = QQmlProperty::read(object, "width").toInt();
But this works only when the object is not marked
pragma Singleton
-- presumably because we are actually instantiating the object in thecomponent.create()
, which the singleton disallows.Is there any way around this? [Incidentally, the other
QQuickView
method doesn't work at all, even on non-singleton objects, because the object is aQtObject
and not anItem
.] -
Qt Champions 2022wrote on 10 Nov 2018, 08:02 last edited by dheerendra 11 Oct 2018, 08:02
It should work as is. It should not make any difference.. Can you post your config.qml ?
-
wrote on 10 Nov 2018, 18:52 last edited by
AppConfig/Config.qml:
import QtQuick 2.0 pragma Singleton QtObject { objectName: "Config" readonly property int width: 37 readonly property int height: 43 }
main.cpp:
int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); if (engine.rootObjects().isEmpty()) return -1; QQmlComponent component(&engine, QUrl(QStringLiteral("qrc:/AppConfig/Config.qml"))); QObject *object = component.create(); int cfgWidth = QQmlProperty::read(object, "width").toInt(); qDebug("Config width = %d", cfgWidth); delete object; return app.exec(); }
This works only if I comment out the
pragma Singleton
from Config.qml. Otherwise it printsQQmlComponent: Component is not ready
and the width read is 0. -
Qt Champions 2022wrote on 11 Nov 2018, 04:20 last edited by dheerendra 11 Nov 2018, 04:22
I have exactly same program and tried. It works like champ. Do you have only above code in Config.qml or something also exist ? Reason is that if the component is not ready, component.create and read function should crash your program. So is it crashing ?
Also check for isError from Component and try to get all the errors using errors() function. It should give some hints.Which version of Qt & platform ?
-
wrote on 11 Nov 2018, 06:45 last edited by vikramg 11 Nov 2018, 06:53
Huh!? Wow that's strange. To answer your questions:
- Yes, that is the entirety of code in Config.qml (I deliberately created a simple example project to illustrate the problem).
- No, the program does not crash. The default "Hello World" application window does pop up on screen. The entirety of Application Output is:
QML debugging is enabled. Only use this in a safe environment. QQmlComponent: Component is not ready Config width = 0
(When the
pragma Singleton
is commented out, it correctly printsConfig width = 37
, and the "not ready" message is not seen). I checked in the debugger, and theobject
is indeed a null pointer in the failing case, but surprisingly theQQmlProperty::read
function does not crash; instead, it returns 0.- Qt version 5.9.0; platform Linux x86-64.
I added the isError/errors() debug instrumentation as you suggested:
QQmlComponent component(&engine, QUrl(QStringLiteral("qrc:/AppConfig/Config.qml"))); QObject *object = component.create(); if (component.isError()) { for (auto e : component.errors()) { qDebug() << e; } }
and in the failing case, it prints out:
QML debugging is enabled. Only use this in a safe environment. QQmlComponent: Component is not ready <Unknown File>: No matching type found, pragma Singleton files cannot be used by QQmlComponent. Config width = 0
This seems to bear out my original hunch that Singleton QML elements cannot be instantiated. But then how does it work for you?? Did this behavior change in later Qt versions?
-
Qt Champions 2022wrote on 11 Nov 2018, 07:42 last edited by dheerendra 11 Nov 2018, 07:43
Can you register the Config.qml component as singleton using the following statement & then try ?
qmlRegisterSingletonType(QStringLiteral("qrc:/MyStyles.qml"),"pthinks.styles",1,0,"PthinkStyle"); -
wrote on 12 Nov 2018, 00:51 last edited by
That does indeed work! Thank you!
qmlRegisterSingletonType(QUrl(QStringLiteral("qrc:/AppConfig/Config.qml")), "com.test.Config", 1, 0, "Config");
1/7