Revision control

Copy as Markdown

// Copyright (C) 2026 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
import Qt.labs.StyleKit
ApplicationWindow {
id: app
width: 1024
height: 800
visible: true
StyleKit.style: Style {
//! [control]
control {
padding: 8
background.radius: 4
}
//! [control]
//! [abstractButton]
abstractButton.background.radius: 4 // all buttons get a radius of 4
checkBox.indicator.radius: 2 // except check boxes, which get a radius of 2
//! [abstractButton]
/* We can only have one theme in the style, so comment out applicationWindow (so that the file compiles)
//! [applicationWindow]
light: Theme {
applicationWindow.background.color: "#f0f0f0"
}
dark: Theme {
applicationWindow.background.color: "#404040"
}
//! [applicationWindow]
*/
//! [button]
button {
background {
width: 120
height: 40
shadow {
opacity: 0.6
color: "gray"
verticalOffset: 2
horizontalOffset: 2
}
color: "cornflowerblue"
gradient: Gradient {
// The gradient is drawn on top of the 'background.color', so
// we use semi-transparent stops to give the button some shading
// while letting the base color show through. This makes it easier
// to change the color, but keep the shading, in the hovered state below.
GradientStop { position: 0.0; color: Qt.alpha("black", 0.0)}
GradientStop { position: 1.0; color: Qt.alpha("black", 0.2)}
}
}
text.color: "white"
hovered.background.color: "royalblue"
pressed.background.scale: 0.95
}
//! [button]
/*
We cannot include two busyIndicators in this file, so we
prefer to compile the custom spinner snippet.
//! [busyIndicator]
busyIndicator {
background {
visible: false
width: 48
height: 48
}
indicator {
fillWidth: true
fillHeight: true
color: "transparent"
border.width: 0
foreground {
radius: 255
color: palette.accent
}
}
}
//! [busyIndicator]
*/
//! [busyIndicator delegate]
busyIndicator {
background {
visible: false
width: 48
height: 48
}
indicator {
fillWidth: true
fillHeight: true
color: "transparent"
border.width: 0
foreground {
radius: 255
color: palette.accent
delegate: Text {
required property DelegateStyle delegateStyle
required property QtObject control
opacity: control.running ? 1 : 0
Behavior on opacity { NumberAnimation{} }
text: "↻"
color: delegateStyle.color
font.pixelSize: 20
RotationAnimation on rotation {
from: 0
to: 360
duration: 1000
loops: Animation.Infinite
running: control.running
}
}
}
}
}
//! [busyIndicator delegate]
//! [checkBox]
checkBox {
// Hide the button background; show only the indicator and text
background.visible: false
indicator {
color: "white"
border.color: "darkslategray"
foreground {
color: "transparent"
image.source: "qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/check.png"
image.color: palette.accent
// Hide the checkmark when the checkbox is not checked
visible: false
}
}
// Show the checkmark when the checkbox is checked
checked.indicator.foreground.visible: true
}
//! [checkBox]
//! [checkDelegate]
checkDelegate {
text.alignment: Qt.AlignHCenter | Qt.AlignVCenter
background {
radius: 0
color: "white"
border.width: 0
}
indicator {
border.color: "darkslategray"
foreground {
color: "transparent"
image.source: "qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/check.png"
image.color: palette.accent
// Hide the checkmark when the checkbox is not checked
visible: false
}
}
hovered.background.color: "#f0f0f0"
// Show the checkmark when the checkbox is checked
checked.indicator.foreground.visible: true
}
//! [checkDelegate]
//! [comboBox]
comboBox {
text.alignment: Qt.AlignHCenter | Qt.AlignVCenter
background.topLeftRadius: 4
background.topRightRadius: 4
indicator {
// Show only the dropdown arrow, not the indicator background
color: "transparent"
border.width: 0
foreground {
image.source: "qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/drop-indicator.png"
image.color: "black"
}
}
}
//! [comboBox]
//! [delayButton]
delayButton {
indicator {
height: 6
fillWidth: true
border.width: 1
alignment: Qt.AlignBottom
foreground {
margins: 2
fillWidth: true
fillHeight: true
color: palette.accent
}
}
}
//! [delayButton]
//! [dial]
dial {
padding: 0
handle.width: 15
handle.height: 15
background {
width: 60
height: 60
radius: 255
}
}
//! [dial]
//! [dialog]
dialog {
text {
padding: 12
alignment: Qt.AlignHCenter | Qt.AlignVCenter
}
background.color: "white"
}
//! [dialog]
//! [dialogButtonBox]
dialogButtonBox {
background {
height: 40
radius: 0
color: "transparent"
border.width: 0
}
}
//! [dialogButtonBox]
//! [drawer]
drawer {
background.color: "white"
}
//! [drawer]
//! [flatButton]
flatButton {
// Hide background normally, show on hover
background.visible: false
hovered.background.visible: true
}
//! [flatButton]
//! [frame]
frame {
background {
color: "#fafafa"
border.color: "#d0d0d0"
radius: 4
}
}
//! [frame]
//! [groupBox]
groupBox {
// A group box is a container for other controls, so we give it some
// padding to avoid the child controls to be too close to the border
padding: 20
// Move the label to the right, to match the radius of the background
text.leftPadding: 6
text.color: "darkslategray"
background {
// Move the frame down, below the text label
topMargin: 30
radius: 6
color: "#f8f8f8"
border.color: "#d0d0d0"
}
}
//! [groupBox]
//! [headerViewDelegate]
headerViewDelegate {
text.alignment: Qt.AlignHCenter | Qt.AlignVCenter
background {
border.width: 1
color: "#f8f8f8"
}
indicator {
color: "transparent"
border.width: 0
alignment: Qt.AlignRight | Qt.AlignVCenter
foreground {
fillWidth: true
fillHeight: true
color: "transparent"
image.color: palette.accent
}
first {
foreground.image.source: "qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/sort-ascending.png"
}
second {
foreground.image.source: "qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/sort-descending.png"
}
}
vertical {
background {
border.width: 1
color: "#d0d0d0"
}
}
}
//! [headerViewDelegate]
//! [itemDelegate]
itemDelegate {
text.alignment: Qt.AlignVCenter | Qt.AlignLeft
background {
radius: 0
color: "white"
border.width: 0
}
hovered.background.color: "#f0f0f0"
}
//! [itemDelegate]
/* We can only have one theme in the style, so comment out label (so that the file compiles)
//! [label]
light: Theme {
// Labels typically have no background, so set background.visible to false.
// Alternatively, hiding the background for labels can be done once for all
// themes by setting Style.label.background.visible: false.
label.background.visible: false
label.text.color: "black"
}
dark: Theme {
label.background.visible: false
label.text.color: "white"
}
//! [label]
*/
//! [menu]
menu {
background {
width: 200
height: 40
border.color: "darkslategray"
radius: 4
}
}
//! [menu]
//! [menuBar]
menuBar {
background {
radius: 0
border.width: 0
}
}
//! [menuBar]
//! [menuBarItem]
menuBarItem {
text.alignment: Qt.AlignLeft | Qt.AlignVCenter
background {
radius: 0
color: "transparent"
border.width: 0
}
hovered.background.color: "#c0c0c0"
}
//! [menuBarItem]
//! [menuItem]
menuItem {
text.alignment: Qt.AlignVCenter | Qt.AlignLeft
background {
width: 200
border.width: 0
}
indicator {
color: "transparent"
border.width: 0
foreground {
image.color: palette.accent
alignment: Qt.AlignCenter
}
first {
alignment: Qt.AlignLeft
foreground.image.source: "qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/check.png"
}
second {
alignment: Qt.AlignRight
foreground.image.source: "qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/arrow-indicator.png"
}
}
hovered.background.color: "#c0c0c0"
}
//! [menuItem]
//! [menuSeparator]
menuSeparator {
background.visible: false
indicator {
width: 188
height: 1
border.width: 0
color: "#c0c0c0"
foreground.visible: false
}
}
//! [menuSeparator]
//! [page]
page {
background {
color: "white"
border.width: 0
}
variations: StyleVariation {
toolBar.background.color: "cornflowerblue"
toolButton.background.color: "skyblue"
toolButton.background.border.color: "aliceblue"
}
}
//! [page]
//! [pageIndicator]
pageIndicator {
background.visible: false
indicator {
width: 5
height: 5
radius: 255
border.width: 0
color: "black"
opacity: 0.45
foreground.visible: false
}
hovered.indicator {
width: 6
height: 6
opacity: 0.7
}
pressed.indicator {
width: 4
height: 4
}
checked.indicator {
width: 7
height: 7
}
checked.hovered.indicator {
width: 8
height: 8
opacity: 0.7
}
}
//! [pageIndicator]
//! [pane]
pane {
background {
width: 200
height: 200
color: "white"
}
}
//! [pane]
//! [popup]
popup {
background {
color: "white"
border.width: 1
border.color: "darkslategray"
radius: 4
}
}
//! [popup]
/*
We cannot include two progressBars in this file, so we
prefer to compile the more complex indeterminate one.
//! [progressBar]
progressBar {
// Hide the background; show only the progress bar
background.visible: false
indicator {
width: 150
height: 8
radius: 4
color: "#e0e0e0"
foreground {
// Set margins to add some space between the progress track and the groove
margins: 2
color: palette.accent
radius: 4
}
}
}
//! [progressBar]
*/
//! [progressBar indeterminate]
progressBar {
indicator {
width: 150
height: 8
foreground {
delegate: StyledItem {
// Draw a pulsating progress track when in indeterminate mode, and a normal track otherwise
width: control.indeterminate ? parent.width : parent.width * control.visualPosition
height: parent.height
opacity: control.indeterminate ? 0.1 : 1.0
SequentialAnimation on opacity {
running: control.indeterminate
loops: Animation.Infinite
NumberAnimation { from: 0.1; to: 1.0; duration: 500; easing.type: Easing.InOutQuad }
NumberAnimation { from: 1.0; to: 0.1; duration: 500; easing.type: Easing.InOutQuad }
}
}
}
}
}
//! [progressBar indeterminate]
//! [radioButton]
radioButton {
// Hide the button background; show only the indicator and text
background.visible: false
indicator {
// Make the indicator circular
radius: 255
foreground {
// The foreground circle is what shows the checked state, so we make
// it a bit smaller than the outer circle by setting margins
margins: 4
radius: 255
// Hide the foreground circle when the radio button is not checked
visible: false
}
}
// Show the foreground circle when the radio button is checked
checked.indicator.foreground.visible: true
}
//! [radioButton]
//! [radioDelegate]
radioDelegate {
text.alignment: Qt.AlignVCenter | Qt.AlignLeft
background {
radius: 0
color: "white"
border.width: 0
}
indicator {
radius: 255
foreground {
margins: 4
visible: false
radius: 255
color: palette.accent
}
}
hovered.background.color: "#f0f0f0"
checked.indicator.foreground.visible: true
}
//! [radioDelegate]
//! [roundButton]
roundButton {
background.radius: 255
text.alignment: Qt.AlignVCenter | Qt.AlignHCenter
}
//! [roundButton]
//! [scrollBar]
scrollBar {
padding: 0
background {
// Set the groove size and color
width: 10
height: 10
color: "white"
}
indicator {
radius: 255
fillWidth: true
width: 10
height: 10
color: "#c0c0c0"
// The indicator is so simple that it doesn't need a foreground
foreground.visible: false
}
vertical {
indicator {
// In vertical mode, the indicator should stretch vertically
// to fill the available height rather than the available width.
fillWidth: false
fillHeight: true
}
}
}
//! [scrollBar]
//! [scrollIndicator]
scrollIndicator {
// A scroll indicator typically has no groove, just a sliding
// indicator. So hide the background, since it represents the groove.
background.visible: false
indicator {
fillWidth: true
width: 5
height: 5
border.width: 0
color: "cornflowerblue"
// The indicator is so simple that it doesn't need a foreground
foreground.visible: false
}
vertical {
indicator {
// In vertical mode, the indicator should stretch vertically
// to fill the available height rather than the available width.
fillWidth: false
fillHeight: true
}
}
}
//! [scrollIndicator]
//! [searchField]
searchField {
// Center the text between the buttons
text.padding: 5
text.alignment: Qt.AlignVCenter | Qt.AlignLeft
text.color: "black"
background.width: 200
indicator {
color: "transparent"
border.width: 0
foreground{
alignment: Qt.AlignCenter
}
// Place the search and clear buttons on the left and right side of the control
// search button
first {
alignment: Qt.AlignLeft
image.color: "black"
image.source: "qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/search-magnifier.png"
}
// clear button
second {
alignment: Qt.AlignRight
image.color: "black"
image.source: "qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/close_circle.png"
}
}
}
//! [searchField]
//! [slider]
slider {
background {
// The background is hidden, but its implicit size still
// determines the overall implicit size of the control.
visible: false
width: 150
height: 50
}
indicator {
// The groove of the slider should fill out the entire width of the control
fillWidth: true
height: 8
radius: 255
color: "#e0e0e0"
foreground {
radius: 255
color: palette.accent
}
}
handle {
width: 24
height: 24
radius: 255
color: "white"
border.color: "#c0c0c0"
}
vertical {
// Transpose relevant geometry
background {
width: 50
height: 150
}
indicator {
fillWidth: false
fillHeight: true
width: 8
}
}
}
//! [slider]
//! [spinBox]
spinBox {
// Center the text between the up/down buttons
text.alignment: Qt.AlignHCenter | Qt.AlignVCenter
indicator {
color: "transparent"
border.width: 0
foreground {
image.source: "qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/arrow-indicator.png"
image.color: "black"
alignment: Qt.AlignCenter
}
// Place the down and up buttons on the left and right side of the control
// up button
first {
alignment: Qt.AlignRight
foreground.rotation: -90
}
// down button
second {
alignment: Qt.AlignLeft
foreground.rotation: 90
}
}
}
//! [spinBox]
//! [scrollView]
scrollView {
// Add some space between the scroll bars and the content area
padding: 2
// For the sake of the example, style the scroll bars in a ScrollView
// differently from the default scroll bars by using a StyleVariation.
variations: StyleVariation {
scrollBar.indicator.color: "cornflowerblue"
}
}
//! [scrollView]
//! [swipeDelegate]
swipeDelegate {
text.alignment: Qt.AlignVCenter | Qt.AlignLeft
background {
radius: 0
color: "white"
border.width: 0
}
hovered.background.color: "#f0f0f0"
}
//! [swipeDelegate]
//! [switchControl]
switchControl {
// For a switch control, we typically don't want a background, only an indicator with a handle
background.visible: false
indicator {
radius: 12
foreground {
// Add some space between the indicator and the foreground track
margins: 2
radius: 12
// The foreground track should only be visible when the switch is checked
visible: false
}
}
checked.indicator.foreground.visible: true
handle {
// Add some space between the handle and the indicator
leftMargin: 2
rightMargin: 2
width: 20
height: 20
radius: 255
color: "white"
}
}
//! [switchControl]
//! [switchDelegate]
switchDelegate {
text.alignment: Qt.AlignVCenter | Qt.AlignLeft
background {
radius: 0
color: "white"
border.width: 0
}
indicator {
radius: 12
foreground {
// Add some space between the indicator and the foreground track
margins: 2
radius: 12
// The foreground track should only be visible when the switch is checked
visible: false
}
}
handle {
// Add some space between the handle and the indicator
leftMargin: 2
rightMargin: 2
width: 20
height: 20
radius: 255
color: "white"
}
hovered.background.color: "#f0f0f0"
checked.indicator.foreground.visible: true
}
//! [switchDelegate]
//! [tabBar]
tabBar {
padding: 0
spacing: -1 // let tab buttons overlap slightly
background {
color: "white"
border.width: 0
}
}
//! [tabBar]
//! [tabButton]
tabButton {
background {
radius: 0
topLeftRadius: 4
topRightRadius: 4
color: "#e8e8e8"
}
checked.background.color: "white"
}
//! [tabButton]
//! [tableViewDelegate]
tableViewDelegate {
text.alignment: Qt.AlignVCenter | Qt.AlignLeft
background {
radius: 0
color: "white"
border.width: 0
}
hovered.background.color: "white"
highlighted.background.color: "darkslategray"
highlighted.hovered.background.color: "darkslategray"
focused {
background.border.width: 2
}
}
//! [tableViewDelegate]
//! [textArea]
textArea {
// Add some space between the text and the border of the text area
padding: 8
text.color: "black"
background {
color: "white"
border.color: "#c0c0c0"
}
focused.background.border.color: palette.accent
}
//! [textArea]
//! [textField]
textField {
// Add some space between the text and the border of the text field
padding: 8
text.alignment: Qt.AlignVCenter
background {
width: 150
color: "white"
border.color: "#c0c0c0"
}
focused.background.border.color: palette.accent
}
//! [textField]
//! [textInput]
textInput {
// Add some space between the text and the border of the text input
padding: 8
text.color: "black"
background {
color: "white"
border.width: 1
border.color: "#c0c0c0"
}
}
//! [textInput]
//! [toolBar]
toolBar {
spacing: 2
background {
radius: 0
height: 40
border.width: 1
}
}
//! [toolBar]
//! [toolButton]
toolButton {
background.radius: 0
}
//! [toolButton]
//! [toolSeparator]
toolSeparator {
background {
// The background is hidden, but its implicit size still
// determines the overall implicit size of the control.
visible: false
width: 10
height: 10
}
indicator {
width: 30
height: 1
border.width: 0
color: "#c0c0c0"
alignment: Qt.AlignCenter
foreground.visible: false
}
vertical {
indicator {
width: 1
height: 30
}
}
}
//! [toolSeparator]
//! [toolTip]
toolTip {
text.padding: 2
background {
width: 20
height: 20
color: "white"
}
}
//! [toolTip]
//! [treeViewDelegate]
treeViewDelegate {
background {
radius: 0
color: "white"
border.width: 0
}
indicator {
width: 18
height: 18
color: "transparent"
border.width: 0
alignment: Qt.AlignLeft | Qt.AlignVCenter
foreground {
fillWidth: true
fillHeight: true
color: "transparent"
image.color: palette.accent
image.source: "qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/arrow-indicator.png"
}
}
highlighted.background.color: "darkslategray"
highlighted.hovered.background.color: "darkslategray"
focused.background.border.width: 2
// For TreeViewDelegate, checked means expanded, so rotate the arrow to point down
checked.indicator.foreground.rotation: 90
}
//! [treeViewDelegate]
//! [tumbler]
tumbler {
background {
height: 200
width: 60
color: "transparent"
border.width: 0
}
}
//! [tumbler]
//! [theme]
light: Theme {
applicationWindow.background.color: "#f0f0f0"
label.text.color: "black"
}
dark: Theme {
applicationWindow.background.color: "#404040"
label.text.color: "white"
}
//! [theme]
}
//! [getControlStyle]
Style {
id: myStyle
property int customButtonType: 0
CustomControl {
controlType: myStyle.customButtonType
background.color: "green"
}
}
//! [getControlStyle]
//! [getControlStyle-function]
function changeButtonColor() {
let customControlStyle = myStyle.getControlStyle(style.customButtonType)
customControlStyle.background.color = "yellowgreen"
// You can also access the style definition in the theme, if it has one
// myStyle.theme.getControlStyle(StyleReader.Button).padding = 10
}
//! [getControlStyle-function]
// The rest of the file is not a part of the docs. It just implements a small
// UI to allow testing the style from the command line using the 'qml' app.
ScrollView {
anchors.fill: parent
Column {
anchors.fill: parent
anchors.margins: 10
spacing: 10
ToolBar {
id: tb
Row {
spacing: tb.spacing
anchors.fill: parent
ToolButton { text: "Tool 1" }
ToolButton { text: "Tool 2" }
ToolSeparator { anchors.verticalCenter: parent.verticalCenter }
ToolButton { text: "Tool 3" }
}
}
ComboBox {
// The user can choose which theme to use
model: StyleKit.style.availableThemeNames
onCurrentTextChanged: StyleKit.style.themeName = currentText
}
Button {
text: "Button"
}
Slider {
width: 200
}
Slider {
height: 200
orientation: Qt.Vertical
}
CheckBox {
text: "CheckBox"
}
RadioButton {
text: "RadioButton"
checked: true
}
RadioButton {
text: "RadioButton"
}
RadioButton {
text: "RadioButton"
}
RoundButton {
text: "RoundButton"
}
Frame {
width: 100
height: 100
clip: true
Flickable {
anchors.fill: parent
contentWidth: 200
contentHeight: 200
ScrollIndicator.vertical: ScrollIndicator {}
ScrollIndicator.horizontal: ScrollIndicator {}
Text {
text: "Test ScrollIndicators"
font.pixelSize: 20
}
}
}
SpinBox {
from: 0
to: 100
value: 50
}
Switch {
text: "Switch"
}
TabBar {
TabButton { text: "Tab 1" }
TabButton { text: "Tab 2" }
TabButton { text: "Tab 3" }
}
TextArea {
width: 200
height: 100
text: "TextArea"
}
TextField {
width: 200
text: "TextField"
}
Page {
header: ToolBar {
ToolButton {
text: "<"
}
}
}
}
}
}