wsys
wsys

Reputation: 385

Change fusion style colors in QML dynamically

I'm developing QML application using Fusion style. I'm using Qt 5.15 lts.
I want to make a function which switch color themes(light mode, dark mode, etc.) in runtime.
The documentation says that changing the color system of fusion style can be done by modifying palette object in QML.
I believe it will be easily done in ApplicationWindow type, but I have to use my custom Window object, rather than ApplicationWindow.
So I tried to it in C++, like below.

// @theme_dark_ and @theme_light_ are pre-defined palette object.
Q_INVOKABLE void Backend::SetDarkMode(const bool flag) {
  qGuiApp->setPalette(flag ? theme_dark_ : theme_light_);
}

I checked setPalette method works before starting QML application(QGuiApplication::exec), but it didn't when QML app is running.
Is there any way to modify palette in Window type in QML, or calling QCoreApplication::setPalette in QML app runtime?
Thanks.

Upvotes: 0

Views: 1073

Answers (1)

Stephen Quan
Stephen Quan

Reputation: 26096

In the following example, I have a Page component where I can set the palette which will be inherited by all its children:

import QtQuick
import QtQuick.Controls
import QtQuick.Layouts

Page {
    palette: AppPalettes.current
    title: "Palette Demo"

    Flickable {
        id: flickable
        anchors.fill: parent
        contentWidth: columnLayout.width
        contentHeight: columnLayout.height
        clip: true
        ScrollBar.vertical: ScrollBar {
            width: 20
            policy: ScrollBar.AlwaysOn
        }
        
        ColumnLayout {
            id: columnLayout
            width: flickable.width - 40
            CheckBox {
                id: darkMode
                text: checked ? qsTr("Dark Mode") : qsTr("Light Mode")
                checked: AppPalettes.darkMode
                onToggled: AppPalettes.darkMode = checked
            }
            
            Label { text: qsTr("Sample Label") }
            CheckBox { text: qsTr("Sample CheckBox") }
            RadioButton { text: qsTr("Sample Radio Button") }
            Button { text: qsTr("Sample Button") }
            ComboBox {
                Layout.preferredWidth: 200
                model: [ "ComboValue 1", "ComboValue 2", "ComboValue 3" ]
            }
            Slider { from: 0; to: 100 }
            ListView {
                model: 20
                Layout.preferredHeight: contentHeight
                delegate: ItemDelegate {
                    text: "ListItem " + (index + 1)
                    onClicked: ListView.view.currentIndex = index
                }
            }
        }
    } 
}

// qmldir
singleton AppPalettes 1.0 AppPalettes.qml

// AppPalettes.qml
pragma Singleton
import QtQuick
AppPalettesPrivate { }

// AppPalettesPrivate.qml
import QtQuick
import QtQuick.Controls
QtObject {
    property bool darkMode: true
    readonly property Palette current: darkMode ? dark : light
    readonly property Palette dark: 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"
    }
    readonly property Palette light: 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: "#eee"
        windowText: "#000"
    }
}

You can Try it Online!

Upvotes: 1

Related Questions