Theming the application with a QML singleton
Styling and theming a QML application can be done in various ways. In this chapter, we will declare a QML singleton with the theme data used by custom components. Moreover, we will also create a custom Page component to handle the toolbar and its default item (back button and page's title).
Please create a new Style.qml file:
pragma Singleton import QtQuick 2.0 QtObject { property color text: "#000000" property color windowBackground: "#eff0f1" property color toolbarBackground: "#eff0f1" property color pageBackground: "#fcfcfc" property color buttonBackground: "#d0d1d2" property color itemHighlight: "#3daee9" }
We declare a QtObject component that will only contain our theme properties. A QtObject is a non-visual QML component.
Declaring a singleton type in QML requires two steps. First you need to use the pragma singleton, it will indicate the use of a single instance of the component. The second step is to register it. This can be done in C++ or by creating a qmldir file. Let's see the second step. Create a new plain-text file called qmldir:
singleton Style 1.0 Style.qml
This simple line will declare a QML singleton type named Style with the version 1.0 from the file named Style.qml.
It is now time to use these theme properties in custom components. Let's see a simple example. Create a new QML file called ToolBarTheme.qml:
import QtQuick 2.0 import QtQuick.Controls 2.0 import "." ToolBar { background: Rectangle { color: Style.toolbarBackground } }
This QML object describes a customized ToolBar. Here, the background element is a simple Rectangle with our color. We can easily access our singleton Style and its theme property using Style.toolbarBackground.
We will now create a QML file PageTheme.qml, with the aim of containing all the code related to the page's toolbar and theme:
import QtQuick 2.0 import QtQuick.Layouts 1.3 import Qt.labs.controls 1.0 import QtQuick.Controls 2.0 import "." Page { property alias toolbarButtons: buttonsLoader.sourceComponent property alias toolbarTitle: titleLabel.text header: ToolBarTheme { RowLayout { anchors.fill: parent ToolButton { background: Image { source: "qrc:/res/icons/back.svg" } onClicked: { if (stackView.depth > 1) { stackView.pop() } } } Label { id: titleLabel Layout.fillWidth: true color: Style.text elide: Text.ElideRight font.pointSize: 30 } Loader { Layout.alignment: Qt.AlignRight id: buttonsLoader } } } Rectangle { color: Style.pageBackground anchors.fill: parent } }
This PageTheme element will customize the page's header. We use our previously created ToolBarTheme. This toolbar only contains a RowLayout element to display items horizontally in one row. This layout contains three elements:
- ToolButton: This is the "back" that displays an image from gallery.qrc and pops the current page if required
- Label: This is the element that displays the page title
- Loader: This is the element that allows a page to dynamically add specific items in this generic toolbar
The Loader element owns a sourceComponent property. In this application, this property can be assigned by PageTheme pages to add specific buttons. These buttons will be instantiated at runtime.
The PageTheme pages also contain a Rectangle element that fits the parent and configures the page background color using the Style.pageBackground.
Now that our Style.qml and PageTheme.qml files are ready, we can update the AlbumListPage.qml file to use it:
import QtQuick 2.6 import QtQuick.Controls 2.0 import "." PageTheme { toolbarTitle: "Albums" ListView { id: albumList model: albumModel spacing: 5 anchors.fill: parent delegate: Rectangle { width: parent.width height: 120 color: Style.buttonBackground Text { text: name font.pointSize: 16 color: Style.text anchors.verticalCenter: parent.verticalCenter } ... } } }
Now that AlbumListPage is a PageTheme element, we do not manipulate header directly. We only need to set the property toolbarTitle to display a nice "Albums" text in the toolbar. We can also enjoy nice colors using properties from the Style singleton.
By centralizing the theme properties in a single file, you can easily change the look and feel of your application. The source code of the project also contains a dark theme.