Search code examples
qtqmlqtquick2

Trouble importing supporting QML files into Main.QML


I'm trying to make a QtQuick app with color themes. I plan to make a few .qml style sheets that define concepts like buttonColor, fontColor and so on. Here's an example of what the style sheets will look like more or less:

pragma Singleton
import QtQuick

QtObject {
    property color bodyTextColor: "white"
    property color headerTextColor: "black"
    property int buttonBorderWidth: 3
    property color buttonColor: "#007bff"
    property color backgroundColor: "#000000"
    property color accentColor: "#6c757d"
    property int fontSize: 16
    property int titleFontSize: fontSize + 8
    property int labelFontSize: fontSize - 16
}

I tried import "ClassicStylesheet.qml" as Styles and it can't find it even though it's in the same root directory with Main.qml (I get a "no such directory" error). Using an absolute path to ClassicStylesheet.qml gets around this and the app runs, but it still doesn't work. I get the following error:

Could not find any constructor for value type QQuickColorValueType to call with value QVariant(QObject*, 0x0) qrc:/[projectname]/Main.qml:31:17: Unable to assign undefined to QColor

All components render in black when running with an absolute path to the style sheet. Here's an example of my Main.qml file using my reusable LargeButton component (which renders fine using defaults, without the stylesheet) to create a main menu button:

import QtQuick
import QtQuick.Controls
import QtQuick.Layouts

import "ClassicStylesheet.qml" as Styles

Window {
    width: 1280
    height: 720
    visible: true
    title: qsTr("Test")

    Rectangle {
        id: menuFrame
        width: 600
        height: 400
        color: "lightgrey"
        anchors.centerIn: parent
        radius: 25

        ColumnLayout {
            anchors.centerIn: parent
            spacing: 10

            LargeButton {
                text: "Settings"
                buttonColor: Styles.buttonColor
                accentColor: Styles.accentColor
                fontColor: Styles.fontColor

                onClicked:
                {

                }
            }
        }
    }
}

Any advice on navigating this? Why doesn't it recognize my file or read its contents? Thanks.


Solution

  • There's no need to import a singleton file. You might need to supply a qmldir file.

    singleton AppThemes 1.0 AppThemes.qml
    

    In the following demo, there are two themes. A "light" and "dark" theme. These are available via the AppThemes singleton. The standard Palette format is used so that it can be assigned at a top-level component and it will be inherited by all controls underneath. Additional parameters, such as fontSize may be added.

    import QtQuick
    import QtQuick.Controls
    import QtQuick.Layouts
    Page {
        title: "AppThemes Demo"
        palette: AppThemes.current.palette
        ColumnLayout {
            RowLayout {
                AppButton { text: "File" }
                AppButton { text: "Edit" }
                AppButton { text: "Settings" }
                AppButton { text: "Help" }
            }
            AppLabel { text: "Pick a Theme" }
            Repeater {
                model: AppThemes.themes
                AppButton {
                    text: modelData
                    checked: modelData === AppThemes.currentName
                    onClicked: AppThemes.currentName = modelData
                }
            }
        }
    }
    
    // qmldir
    singleton AppThemes 1.0 AppThemes.qml
    
    // AppThemes.qml
    pragma Singleton
    import QtQuick
    AppThemesPrivate {
    }
    
    // AppThemesPrivate.qml
    import QtQuick
    QtObject {
        id: appThemes
        readonly property list<string> themes: ["light","dark"]
        property string currentName: "light"
        readonly property AppStyle current: appThemes[currentName] || light
        property AppStyle light: AppStyle {
        }
        property AppStyle dark: AppStyle {
            fontSize: 14
            palette: Palette {
                alternateBase: "#000"
                base: "#000"
                button: "#111"
                buttonText: "#fff"
                dark: "#666"
                highlight: "#d73"
                highlightedText: "#000"
                light: "#000"
                mid: "#444"
                midlight: "#333"
                placeholderText: "#80000000"
                shadow: "#888"
                text: "#fff"
                window: "#222"
                windowText: "#fff"
            }
        }
    }
    
    // AppStyle.qml
    import QtQuick
    import QtQuick.Controls
    QtObject {
        property int fontSize: 10
        property Palette palette: Palette {
            alternateBase: "#fff"
            base: "#fff"
            button: "#eee"
            buttonText: "#000"
            dark: "#999"
            highlight: "#38c"
            highlightedText: "#fff"
            light: "#fff"
            mid: "#bbb"
            midlight: "#ccc"
            placeholderText: "#80000000"
            shadow: "#777"
            text: "#000"
            window: "#fff"
            windowText: "#000"
        }
    }
    
    // AppButton.qml
    import QtQuick
    import QtQuick.Controls
    Button {
        font.pointSize: AppThemes.current.fontSize
    }
    
    // AppLabel.qml
    import QtQuick
    import QtQuick.Controls
    Label {
        font.pointSize: AppThemes.current.fontSize
    }
    

    You can Try it Online!

    References: