[SOLVED] QML Singleton Problem
-
I specified
@
pragma singleton
@as the first line in MySingleton.qml and have
@property string myText: “”
@in MySingleton.qml, specified
@
import “.”
@at the top of main.qml, and added the qmldir file in their common directory with
@
singleton MySingleton MySingleton.qml
@When I have
@
property string mySingletonText: MySingleton.myText
@in main.qml I get the error
bq. qrc:/qml/main.qml:11: ReferenceError: MySingleton is not defined
but MySingleton.qml is specified in my .pro and .qrc files.
When I have
@
MySingleton{
id: singleton
}
@in main.qml I get the error
bq. qrc:/qml/MySingleton.qml:1:1: pragma Singleton used with a non composite singleton type MySingleton
I tried this because I assumed (perhaps mistakenly) that this would be the way to access signals and functions.
Any help would be appreciated.
Thanks.
Steve
-
[quote author="SteveG" date="1394399218"]I specified
@
pragma singleton
@as the first line in MySingleton.qml and have
@property string myText: “”
@in MySingleton.qml, specified
@
import “.”
@at the top of main.qml, and added the qmldir file in their common directory with
@
singleton MySingleton MySingleton.qml
@When I have
@
property string mySingletonText: MySingleton.myText
@in main.qml I get the error
bq. qrc:/qml/main.qml:11: ReferenceError: MySingleton is not defined
but MySingleton.qml is specified in my .pro and .qrc files.
[/quote]There is a limitation with QML-only singletons at the moment - you need to use a full module import with a qmldir file and not just a directory import (with implicit qmldir file). So import "." will not work, you'll need a qmldir file like
@
singleton MySingleton 1.0 MySingleton.qml
@and then import it via a module import (something like 'import MyModule 1.0', not 'import "relative/dir"').
-
Alan,
I'll try what you suggested. Is this "limitation" due to a bug because I followed a documented approach that didn't work?
BTW, are there any plans to allow QML singletons to have signals and functions that other QML types can respond to and call, respectively?
Thank you.
Steve
-
Alan,
I have the qmldir file in my qml directory and changed the contents to
@
singleton MyNewSingleton 1.0 MySingleton.qml
@I also changed the import statement to
@
import MyNewSingleton 1.0
@but Qt Creator 3.0.1 shows this with a red underline and I get the error message
bq. qrc:/qml/main.qml:2:1: module "MyNewSingleton" is not installed
when I run my project. I even added
@
QML_IMPORT_PATH += $$PWD/qml
@to my .pro file but it made no difference.
Do I need to add qmlRegisterSingletonType or something similar to my main.cpp file?
Thanks.
Steve
-
[quote author="SteveG" date="1394799985"]
I'll try what you suggested. Is this "limitation" due to a bug because I followed a documented approach that didn't work?
[/quote]
It's a limitation of the current implementation that we hope to remove some day. The docs are not... that great right now.[quote author="SteveG" date="1394799985"]
BTW, are there any plans to allow QML singletons to have signals and functions that other QML types can respond to and call, respectively?
[/quote]They already have that, like any exposed QObject.
[quote author="SteveG" date="1394801664"]Alan,
I have the qmldir file in my qml directory and changed the contents to
@
singleton MyNewSingleton 1.0 MySingleton.qml
@I also changed the import statement to
@
import MyNewSingleton 1.0
@but Qt Creator 3.0.1 shows this with a red underline and I get the error message
bq. qrc:/qml/main.qml:2:1: module "MyNewSingleton" is not installed
when I run my project. I even added
@
QML_IMPORT_PATH += $$PWD/qml
@to my .pro file but it made no difference.
[/quote]That's not how imports work (they operate on folders, not types). If you added the qml directory as an import path, then the module import you used would be looking for a folder $$PWD/qml/MyNewSingleton .
But you can also import a relative directory, like
@
import "MySingletonsDir"
@or
@
import "."
@So long as it's a directory with that qmldir file, it should pick up the
singleton type. -
Alan,
I've tried several gyrations and still can't get it to work. Please let me know the following.
- What should the directory structure be?
@
I have:
main.cpp
simpleSingleton.pro
simpleSingleton.qrc
qml - Directory
main.qml
MyNewSingleton - Directory
MySingleton.qml
qmldir
@- What should the qmldir file contain and where should it reside?
@
I have:
singleton MyNewSingleton MySingleton.qml
@- Where should the QML singleton file reside?
- What should the .pro file contain?
@
I have:
QT += qml quick
TARGET = SimpleSingletonTest
RESOURCES += simpleSingletonTest.qrc
SOURCES += $$PWD/main.cpp
OTHER_FILES +=
qml/main.qml
qml/MyNewSingleton/MySingleton.qml
@- What should the .qrc file contain?
@
I have:
<RCC>
<qresource prefix="/">
<file>qml/main.qml</file>
<file>qml/MyNewSingleton/MySingleton.qml</file>
</qresource>
</RCC>
@- What should the import in main.qml be?
@
I have:
import "MyNewSingleton"
@- How should the QML singleton be referenced in main.qml?
@
I have:
property string mySingleton1: MyNewSingleton.intProperty
property string mySingleton2: MySingleton.intPropertywhich results in
qrc:/qml/main.qml:10: ReferenceError: MyNewSingleton is not defined
qrc:/qml/main.qml:11: ReferenceError: MySingleton is not defined
@bq. They already have that, like any exposed QObject.
Can you reference an example where a QML singleton has signals and funcions that are used by another QML type?
Thanks.
Steve
- What should the directory structure be?
-
I think you just missed the version number on the import (actually important in this case, I should have mentioned this).
Here's a quick example that I whipped up and verified to work. It just runs using the qml binary, but the adaptation to use a custom C++ shell and QRC should be straightforward:
./main.qml:
@
import QtQuick.Window 2.1
import QtQuick 2.1
import "MyDir" 1.0Window {
width: 480
height: 360
color: "lightsteelblue"
visible: true
Rectangle {
id: col
anchors.fill: parent
anchors.margins: 48
color: "goldenrod"
Text {
id: txt
text: CentralData.textual
anchors.centerIn: parent
}
Connections {
target: CentralData
onTock: txt.text = "tock"
}
MouseArea {
anchors.fill: parent
onClicked: CentralData.tick(txt);
}
}
}
@./MyDir/qmldir:
@
singleton CentralData 1.0 CentralData.qml
@./MyDir/CentralData.qml:
@
pragma Singleton
import QtQml 2.0QtObject {
id: single
property string textual: "Initial String"
signal tock
function tick(obj) {
obj.text = "tick"
}
property QtObject tim: Timer {
interval: 1500
repeat: true
running: true
onTriggered: single.tock();
}
}
@Of course, it's shameful that there isn't a proper example somewhere. I should add one...
-
Alan,
bq. the adaptation to use a custom C++ shell and QRC should be straightforward
It's not. Your example runs with qmlscene but I can't get it to work with a main.cpp and .pro and .qrc files, even with modifying one or both of your QML files. Can you whip up something based on your example?
Thanks.
Steve
-
Alan,
One more thing. When I mouse over the import "MyDir" 1.0 statement in Qt Creator 3.0.1 it correctly shows the location of MyDir. However, when I run the project I get the error message
bq. qrc:/qml/main.qml:3:1: "MyDir": no such directory
When I specify import "." instead, I get several error messages like
bq. qrc:/qml/main.qml:21: ReferenceError: CentralData is not defined
Steve
-
[quote author="SteveG" date="1395198709"]Alan,
bq. the adaptation to use a custom C++ shell and QRC should be straightforward
It's not. Your example runs with qmlscene but I can't get it to work with a main.cpp and .pro and .qrc files, even with modifying one or both of your QML files. Can you whip up something based on your example?
[/quote]Sure. To save time, I didn't spend any thinking on good names for the files ;) . Tested with Qt 5.2.1.
Only thing that wasn't straightforward when I tried is that QQmlApplcationEngine's string constructor didn't seem to recognize the 'qrc:' (probably documented behavior). Wrapping with the QUrl constructor solved that.
main.cpp:
@
#include <QtGui/QGuiApplication>
#include <QtQml/QQmlApplicationEngine>int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine qqae(QUrl("qrc:///qml/testable2/main.qml"));
return app.exec();
}
@testable.pro:
@
TEMPLATE = app
SOURCES += main.cpp
QT += qmlRESOURCES +=
res.qrc
@res.qrc:
@
<RCC>
<qresource prefix="/" lang="qml">
<file>qml/testable2/main.qml</file>
<file>qml/testable2/MyDir/CentralData.qml</file>
<file>qml/testable2/MyDir/qmldir</file>
</qresource>
</RCC>
@ -
Alan,
I added the qmldir file to my .qrc file and it now works.
THANK YOU!!!
Steve
BTW, you may want to include this example in Qt 5.3 or later.