Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically change Material theme in QML

What is the best way to handle theme changes in QML? I noticed some controls like Switch And ApplicationWindow do this automatically, but others like Text and Rectangle just don't!

Is it at all possible to avoid having to check which theme is currently set and then each time set the color accordingly? (color: theme.position < 1 ? "black" : "white")

main.qml

import QtQuick 2.13
import QtQuick.Controls 2.13
import QtQuick.Controls.Material 2.13

//ok:  the background color changes automatically when the theme changes
ApplicationWindow {
    id: root
    visible: true
    width: 1366
    height: 768
    title: qsTr("Theme")

    Material.theme: theme.position < 1 ? Material.Light : Material.Dark

    //ok:  the text color changes automatically when the theme changes
    Switch {
        id: theme
        anchors.right: parent.right
        anchors.top: parent.top
        anchors.margins: 10
        text: "Dark theme"
        checked: false
    }

    //not ok: the background is always white
    Rectangle {
        anchors.centerIn: parent
        width: 200
        height: width

        //not ok: the color is always black
        Text {
            anchors.centerIn: parent
            text: "some text"
            font.pixelSize: 40
        }
    }
}

qtquickcontrols2.conf

[Controls]
Style=Material

[Material]
Theme=Dark
Accent=Orange
Primary=BlueGrey
like image 748
luffy Avatar asked Jul 12 '26 02:07

luffy


1 Answers

Text and Rectangle are primitives from Qt Quick, which means that they don't understand Qt Quick Controls' Material style colour propagation. You can use Label and Frame instead:

import QtQuick 2.13
import QtQuick.Controls 2.13
import QtQuick.Controls.Material 2.13

ApplicationWindow {
    id: root
    visible: true
    width: 1366
    height: 768
    title: qsTr("Theme")

    Material.theme: theme.position < 1 ? Material.Light : Material.Dark

    Switch {
        id: theme
        anchors.right: parent.right
        anchors.top: parent.top
        anchors.margins: 10
        text: "Dark theme"
        checked: false
    }

    Frame {
        anchors.centerIn: parent
        width: 200
        height: width

        Label {
            anchors.centerIn: parent
            text: "some text"
            font.pixelSize: 40
        }
    }
}

Note that Frame will consume mouse events, so if you don't want that, you'll need to use e.g. Control, and handle the colours yourself using the Material style's attached properties:

Control {
    anchors.centerIn: parent
    width: 200
    height: width
    background: Rectangle {
        color: parent.Material.background
        border.color: parent.Material.foreground
    }

    Label {
        anchors.centerIn: parent
        text: "some text"
        font.pixelSize: 40
    }
}
like image 149
Mitch Avatar answered Jul 15 '26 02:07

Mitch



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!