How to create QML singleton
-
I am sorry to ask this question but after reading all documentation and trying to google it I am still not able to create and use singleton on QML :-(
I have following file:
qml/EPGColors.qml:
pragma Singleton import QtQuick QtObject { readonly property color pastProgColor: "#e4e4e4" }I have added it to cmakefile:
set_source_files_properties(qml/EPGColors.qml PROPERTIES QT_QML_SINGLETON_TYPE TRUE) qt6_add_qml_module(${TARGET} URI ProgrammeGuide QML_FILES qml/epg.qml qml/EPGItem.qml qml/EPGSwitch.qml qml/EPGTabBar.qml qml/EPGTabButton.qml qml/EPGColors.qml NO_RESOURCE_TARGET_PATH VERSION 1.0 )Now, I am trying to use it in qml/EPGItem.qml:
property color myColor: EPGColors.pastProgColorAnd I get this error:
qrc:/qml/EPGItem.qml:40:5: Unable to assign [undefined] to QColorIt seems to be aligned with documentation: https://doc.qt.io/qt-6/qt-target-qml-sources.html#source-file-properties
What am I doing wrong?
Thanks!
-
I am sorry to ask this question but after reading all documentation and trying to google it I am still not able to create and use singleton on QML :-(
I have following file:
qml/EPGColors.qml:
pragma Singleton import QtQuick QtObject { readonly property color pastProgColor: "#e4e4e4" }I have added it to cmakefile:
set_source_files_properties(qml/EPGColors.qml PROPERTIES QT_QML_SINGLETON_TYPE TRUE) qt6_add_qml_module(${TARGET} URI ProgrammeGuide QML_FILES qml/epg.qml qml/EPGItem.qml qml/EPGSwitch.qml qml/EPGTabBar.qml qml/EPGTabButton.qml qml/EPGColors.qml NO_RESOURCE_TARGET_PATH VERSION 1.0 )Now, I am trying to use it in qml/EPGItem.qml:
property color myColor: EPGColors.pastProgColorAnd I get this error:
qrc:/qml/EPGItem.qml:40:5: Unable to assign [undefined] to QColorIt seems to be aligned with documentation: https://doc.qt.io/qt-6/qt-target-qml-sources.html#source-file-properties
What am I doing wrong?
Thanks!
What's in EPGItem.qml? Do you import your module there?
-
I have deleted build folder and now there is
singleton EPGColors 1.0 qml/EPGColors.qmlin qmldir file.
I have added import to EPGItem.qml:
import QtQuick import Qt5Compat.GraphicalEffects // required for Qt < 6.5 // import QtQuick.Effects // not available in Qt < 6.5 import ProgrammeGuide Item { id: progItem // ... property color pastProgColor: EPGColors.pastProgColor // ... }And now I get this message that is even more confusing:
qrc:/qml/EPGItem.qml:42: TypeError: EPGColors was a singleton at compile time, but is not a singleton anymore. -
I do not know how to attach file, so this is cope and paste of minimal example:
CMakeList.txt
cmake_minimum_required(VERSION 3.16) project(SingletonTest VERSION 0.1 LANGUAGES CXX) set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(Qt6 6.4 REQUIRED COMPONENTS Quick) qt_standard_project_setup() qt_add_executable(appSingletonTest main.cpp ) set_source_files_properties(qml/Colors.qml PROPERTIES QT_QML_SINGLETON_TYPE TRUE) qt_add_qml_module(appSingletonTest URI SingletonTest VERSION 1.0 QML_FILES qml/main.qml QML_FILES qml/Colors.qml ) # Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1. # If you are developing for iOS or macOS you should consider setting an # explicit, fixed bundle identifier manually though. set_target_properties(appSingletonTest PROPERTIES # MACOSX_BUNDLE_GUI_IDENTIFIER com.example.appSingletonTest MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} MACOSX_BUNDLE TRUE WIN32_EXECUTABLE TRUE ) target_link_libraries(appSingletonTest PRIVATE Qt6::Quick ) include(GNUInstallDirs) install(TARGETS appSingletonTest BUNDLE DESTINATION . LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} )main.cpp:
#include <QGuiApplication> #include <QQmlApplicationEngine> int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQmlApplicationEngine engine; const QUrl url(u"qrc:/SingletonTest/qml/main.qml"_qs); QObject::connect( &engine, &QQmlApplicationEngine::objectCreationFailed, &app, []() { QCoreApplication::exit(-1); }, Qt::QueuedConnection); engine.load(url); return app.exec(); }qml/main.qml:
import QtQuick import SingletonTest Window { width: 640 height: 480 visible: true title: qsTr("Hello World") Rectangle { width: parent.width/2 height: parent.height/2 anchors.centerIn: parent color: Colors.myColor } }qml/Colors.qml:
pragma Singleton import QtQuick QtObject { id: colors readonly property color myColor: "red" }When I run it I get this message:
qrc:/SingletonTest/qml/main.qml:14: TypeError: Colors was a singleton at compile time, but is not a singleton anymore. -
I do not know how to attach file, so this is cope and paste of minimal example:
CMakeList.txt
cmake_minimum_required(VERSION 3.16) project(SingletonTest VERSION 0.1 LANGUAGES CXX) set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(Qt6 6.4 REQUIRED COMPONENTS Quick) qt_standard_project_setup() qt_add_executable(appSingletonTest main.cpp ) set_source_files_properties(qml/Colors.qml PROPERTIES QT_QML_SINGLETON_TYPE TRUE) qt_add_qml_module(appSingletonTest URI SingletonTest VERSION 1.0 QML_FILES qml/main.qml QML_FILES qml/Colors.qml ) # Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1. # If you are developing for iOS or macOS you should consider setting an # explicit, fixed bundle identifier manually though. set_target_properties(appSingletonTest PROPERTIES # MACOSX_BUNDLE_GUI_IDENTIFIER com.example.appSingletonTest MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} MACOSX_BUNDLE TRUE WIN32_EXECUTABLE TRUE ) target_link_libraries(appSingletonTest PRIVATE Qt6::Quick ) include(GNUInstallDirs) install(TARGETS appSingletonTest BUNDLE DESTINATION . LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} )main.cpp:
#include <QGuiApplication> #include <QQmlApplicationEngine> int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQmlApplicationEngine engine; const QUrl url(u"qrc:/SingletonTest/qml/main.qml"_qs); QObject::connect( &engine, &QQmlApplicationEngine::objectCreationFailed, &app, []() { QCoreApplication::exit(-1); }, Qt::QueuedConnection); engine.load(url); return app.exec(); }qml/main.qml:
import QtQuick import SingletonTest Window { width: 640 height: 480 visible: true title: qsTr("Hello World") Rectangle { width: parent.width/2 height: parent.height/2 anchors.centerIn: parent color: Colors.myColor } }qml/Colors.qml:
pragma Singleton import QtQuick QtObject { id: colors readonly property color myColor: "red" }When I run it I get this message:
qrc:/SingletonTest/qml/main.qml:14: TypeError: Colors was a singleton at compile time, but is not a singleton anymore.What if you put the QML files in the root folder of the project?
Colors.qmlinstead ofqml/Colors.qmlAlso I'd remove the second
QML_FILESinqt_add_qml_module -
What if you put the QML files in the root folder of the project?
Colors.qmlinstead ofqml/Colors.qmlAlso I'd remove the second
QML_FILESinqt_add_qml_moduleIf I move Colors.qml to root folder and change CMakeList.txt accordingly:
set_source_files_properties(Colors.qml PROPERTIES QT_QML_SINGLETON_TYPE TRUE) qt_add_qml_module(appSingletonTest URI SingletonTest VERSION 1.0 QML_FILES qml/main.qml Colors.qml )I get this error when I run the application:
qrc:/SingletonTest/qml/main.qml:14: ReferenceError: Colors is not defined -
If I move Colors.qml to root folder and change CMakeList.txt accordingly:
set_source_files_properties(Colors.qml PROPERTIES QT_QML_SINGLETON_TYPE TRUE) qt_add_qml_module(appSingletonTest URI SingletonTest VERSION 1.0 QML_FILES qml/main.qml Colors.qml )I get this error when I run the application:
qrc:/SingletonTest/qml/main.qml:14: ReferenceError: Colors is not definedIt seems all QML files must be in root folder including some other custom components files.
If I do this, it works:
set_source_files_properties(Colors.qml PROPERTIES QT_QML_SINGLETON_TYPE TRUE) qt_add_qml_module(appSingletonTest URI SingletonTest VERSION 1.0 QML_FILES main.qml Colors.qml SomeComponent.qml )This strange, so far I put all my QML files to dedicated folder (qml/) to separate it from C++ and everything was working (see my first example code) - only the singleton causes some problem.
I could consider this as workaround but I do not like it since I will mix QML with C++ and it will be a mess :-(
EDIT: It seems that this construction works too:
set_source_files_properties(qmlfiles/Colors.qml PROPERTIES QT_QML_SINGLETON_TYPE TRUE) set_source_files_properties(qmlfiles/main.qml PROPERTIES QT_RESOURCE_ALIAS main.qml) set_source_files_properties(qmlfiles/Colors.qml PROPERTIES QT_RESOURCE_ALIAS Colors.qml) set_source_files_properties(qmlfiles/SomeComponent.qml PROPERTIES QT_RESOURCE_ALIAS SomeComponent.qml) qt_add_qml_module(appSingletonTest URI SingletonTest VERSION 1.0 QML_FILES qmlfiles/main.qml qmlfiles/Colors.qml qmlfiles/SomeComponent.qml ) -
It seems all QML files must be in root folder including some other custom components files.
If I do this, it works:
set_source_files_properties(Colors.qml PROPERTIES QT_QML_SINGLETON_TYPE TRUE) qt_add_qml_module(appSingletonTest URI SingletonTest VERSION 1.0 QML_FILES main.qml Colors.qml SomeComponent.qml )This strange, so far I put all my QML files to dedicated folder (qml/) to separate it from C++ and everything was working (see my first example code) - only the singleton causes some problem.
I could consider this as workaround but I do not like it since I will mix QML with C++ and it will be a mess :-(
EDIT: It seems that this construction works too:
set_source_files_properties(qmlfiles/Colors.qml PROPERTIES QT_QML_SINGLETON_TYPE TRUE) set_source_files_properties(qmlfiles/main.qml PROPERTIES QT_RESOURCE_ALIAS main.qml) set_source_files_properties(qmlfiles/Colors.qml PROPERTIES QT_RESOURCE_ALIAS Colors.qml) set_source_files_properties(qmlfiles/SomeComponent.qml PROPERTIES QT_RESOURCE_ALIAS SomeComponent.qml) qt_add_qml_module(appSingletonTest URI SingletonTest VERSION 1.0 QML_FILES qmlfiles/main.qml qmlfiles/Colors.qml qmlfiles/SomeComponent.qml )@KejPi open a bugreport because QML SINGLETON doesn't work if not in root folder
-
@KejPi open a bugreport because QML SINGLETON doesn't work if not in root folder
-
I do not know why the one from the post does not work, but singletons from subdirectories work.
I used here
@Mesrine aaah - good to know. just porting my apps from QMake to CMake. next step will be to modernize my apps, where I'll need QML SINGLETONS, too
-
It seems all QML files must be in root folder including some other custom components files.
If I do this, it works:
set_source_files_properties(Colors.qml PROPERTIES QT_QML_SINGLETON_TYPE TRUE) qt_add_qml_module(appSingletonTest URI SingletonTest VERSION 1.0 QML_FILES main.qml Colors.qml SomeComponent.qml )This strange, so far I put all my QML files to dedicated folder (qml/) to separate it from C++ and everything was working (see my first example code) - only the singleton causes some problem.
I could consider this as workaround but I do not like it since I will mix QML with C++ and it will be a mess :-(
EDIT: It seems that this construction works too:
set_source_files_properties(qmlfiles/Colors.qml PROPERTIES QT_QML_SINGLETON_TYPE TRUE) set_source_files_properties(qmlfiles/main.qml PROPERTIES QT_RESOURCE_ALIAS main.qml) set_source_files_properties(qmlfiles/Colors.qml PROPERTIES QT_RESOURCE_ALIAS Colors.qml) set_source_files_properties(qmlfiles/SomeComponent.qml PROPERTIES QT_RESOURCE_ALIAS SomeComponent.qml) qt_add_qml_module(appSingletonTest URI SingletonTest VERSION 1.0 QML_FILES qmlfiles/main.qml qmlfiles/Colors.qml qmlfiles/SomeComponent.qml ) -
I do not know why the one from the post does not work, but singletons from subdirectories work.
I used here
-
I do not know how to attach file, so this is cope and paste of minimal example:
CMakeList.txt
cmake_minimum_required(VERSION 3.16) project(SingletonTest VERSION 0.1 LANGUAGES CXX) set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(Qt6 6.4 REQUIRED COMPONENTS Quick) qt_standard_project_setup() qt_add_executable(appSingletonTest main.cpp ) set_source_files_properties(qml/Colors.qml PROPERTIES QT_QML_SINGLETON_TYPE TRUE) qt_add_qml_module(appSingletonTest URI SingletonTest VERSION 1.0 QML_FILES qml/main.qml QML_FILES qml/Colors.qml ) # Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1. # If you are developing for iOS or macOS you should consider setting an # explicit, fixed bundle identifier manually though. set_target_properties(appSingletonTest PROPERTIES # MACOSX_BUNDLE_GUI_IDENTIFIER com.example.appSingletonTest MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} MACOSX_BUNDLE TRUE WIN32_EXECUTABLE TRUE ) target_link_libraries(appSingletonTest PRIVATE Qt6::Quick ) include(GNUInstallDirs) install(TARGETS appSingletonTest BUNDLE DESTINATION . LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} )main.cpp:
#include <QGuiApplication> #include <QQmlApplicationEngine> int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQmlApplicationEngine engine; const QUrl url(u"qrc:/SingletonTest/qml/main.qml"_qs); QObject::connect( &engine, &QQmlApplicationEngine::objectCreationFailed, &app, []() { QCoreApplication::exit(-1); }, Qt::QueuedConnection); engine.load(url); return app.exec(); }qml/main.qml:
import QtQuick import SingletonTest Window { width: 640 height: 480 visible: true title: qsTr("Hello World") Rectangle { width: parent.width/2 height: parent.height/2 anchors.centerIn: parent color: Colors.myColor } }qml/Colors.qml:
pragma Singleton import QtQuick QtObject { id: colors readonly property color myColor: "red" }When I run it I get this message:
qrc:/SingletonTest/qml/main.qml:14: TypeError: Colors was a singleton at compile time, but is not a singleton anymore.I have used your minimal example and works ok :) .
The only thing I changed was that instead of
CMakeList.txti namedCMakeLists.txt.I have tested it with qt(shared libraries) 6.5,6.6,6.7 in Linux.
Make sure you are using the correct
CMakeLists.txt.
And let us know your platform and Qt version. -
Yes, it was only typo, I use the CMakeLists.txt created by Qt Creator.
I am running it on MacOS 14.2, Qt version 6.5.3@KejPi
Do you run the application that is on the build directory or the installed one?Try putting
set_source_files_properties(qml/Colors.qml PROPERTIES QT_QML_SINGLETON_TYPE TRUE)before
qt_add_executable(appSingletonTest main.cpp )in your minimal example.
If that does not work try removing some macos properties in the CMakeLists.txt.
If nothing works I would say you can open a bug as suggested by @ekkescorner -
@KejPi
Do you run the application that is on the build directory or the installed one?Try putting
set_source_files_properties(qml/Colors.qml PROPERTIES QT_QML_SINGLETON_TYPE TRUE)before
qt_add_executable(appSingletonTest main.cpp )in your minimal example.
If that does not work try removing some macos properties in the CMakeLists.txt.
If nothing works I would say you can open a bug as suggested by @ekkescorner