c++qtqml

Cannot define Object Types through QML Documents


I have spent days researching and trying to figure this out, it should just work - but does not.

I am attempting to create and use a simple QML object as a single source of setting for my project.

As a test I have created a new Qt 6.7.3 QML project, and I added a new .qml file "TestQmlObj.qml" with a few properties.

Intellisense works, but I consistently get Unable to assign [undefined] to errors when run.

TestQmlObj.qml

pragma Singleton
import QtQuick

QtObject {

    readonly property color primaryColor: "red"
    readonly property color secondaryColor: "#FFC107"
    readonly property color backgroundColor: "#FFFFFF"

    readonly property font mainfont: Qt.font({
        family: "Arial",
        pointSize: 12,
        weight: Font.Normal
    })

    readonly property font headerFont: Qt.font({
        family: "Arial",
        pointSize: 16,
        weight: Font.Bold
    })
}

I then tried to use these properties in the Main.qml file.

Main.qml

import QtQuick

Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")

    Rectangle {
        anchors.fill: parent
        //color: "red"
        color: TestQmlObj.primaryColor
        //color: TestQmlObj.backgroundColor

        Text {
            text: qsTr("text")
            font: TestQmlObj.headerFont
        }
    }
}

I have tried all kinds of suggested changes but in all cases I receive the following error and the color does not change.

qrc:/qt/qml/QmlObjTypes/Main.qml:13:9: Unable to assign [undefined] to QColor

CMakeLists.txt

cmake_minimum_required(VERSION 3.16)

project(QmlObjTypes VERSION 0.1 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(Qt6 REQUIRED COMPONENTS Quick)

qt_standard_project_setup(REQUIRES 6.5)

qt_add_executable(appQmlObjTypes
    main.cpp
)

qt_add_qml_module(appQmlObjTypes
    URI QmlObjTypes
    VERSION 1.0
    QML_FILES
        Main.qml
        TestQmlObj.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(appQmlObjTypes PROPERTIES
#    MACOSX_BUNDLE_GUI_IDENTIFIER com.example.appQmlObjTypes
    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(appQmlObjTypes
    PRIVATE Qt6::Quick
)

include(GNUInstallDirs)
install(TARGETS appQmlObjTypes
    BUNDLE DESTINATION .
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)

Solution

  • The reason you are unable to access TestQmlObj is because you are attempting to use it as a singleton, but you have not finished declaring it as such. The docs describe two methods for declaring singletons:

    1. If you define your singleton from QML, you must label it with pragma Singleton AND you must add an entry into the qmldir file of your module. The best way to do that is by setting the source property in your CMakeLists.txt file.
    set_source_files_property(TestQmlObj.qml PROPERTIES QT_QML_SINGLETON_TYPE TRUE)
    
    1. The other way is to define your singleton object from C++ using the QML_SINGLETON macro.
    class MySingleton : public QObject
    {
        Q_OBJECT
        QML_SINGLETON
        QML_ELEMENT
    public:
        MySingleton(QObject *parent = nullptr) : QObject(parent) {
            // ...
        }
    };
    

    Since you have defined your object in QML, you should use option 1 and make sure you update your CMakeLists.txt file.