Qt 5.6 | Qt Labs Controls | Customizing Qt Labs Controls

Qt 5.6.3 Reference Documentation

# Customizing Qt Labs Controls

Qt Labs Controls consist of a hierarchy (tree) of items. In order to provide a custom look and feel, the default QML implementation of each item can be replaced with a custom one. The following snippets present the default implementations of various items. These can be used as a starting point to implement a custom look and feel.

## Customizing BusyIndicator

BusyIndicator consists of two visual items: background and contentItem.

#### Background

BusyIndicator has no background item by default.

#### Content item

      contentItem: BusyRing {
          id: ring
          implicitWidth: 48
          implicitHeight: 48
          opacity: control.running ? 1 : 0

          Behavior on opacity { OpacityAnimator { duration: 250 } }

          BusyRingAnimator {
              target: ring
              running: control.visible && control.running
          }
      }

## Customizing Button

Button consists of two visual items: background and label.

#### Background

      background: Rectangle {
          implicitWidth: 100
          implicitHeight: 40
          opacity: enabled ? 1 : 0.3
          color: control.pressed ? (control.highlighted ? "#585a5c" : "#e4e4e4") : (control.highlighted ? "#353637" : "#f6f6f6")
          border.color: control.pressed ? "#26282a" : "#353637"
      }

#### Label

      label: Text {
          x: control.leftPadding
          y: control.topPadding
          width: control.availableWidth
          height: control.availableHeight
          text: control.text
          font: control.font
          opacity: enabled || highlighted ? 1 : 0.3
          color: control.highlighted ? "#ffffff" : (control.pressed ? "#26282a" : "#353637")
          horizontalAlignment: Text.AlignHCenter
          verticalAlignment: Text.AlignVCenter
          elide: Text.ElideRight
      }

## Customizing CheckBox

CheckBox consists of three visual items: background, label and indicator.

#### Background

CheckBox has no background item by default.

#### Label

      label: Text {
          x: control.mirrored ? control.leftPadding : (indicator.x + indicator.width + control.spacing)
          y: control.topPadding
          width: control.availableWidth - indicator.width - control.spacing
          height: control.availableHeight

          text: control.text
          font: control.font
          color: control.pressed ? "#26282a" : "#353637"
          elide: Text.ElideRight
          visible: control.text
          horizontalAlignment: Text.AlignLeft
          verticalAlignment: Text.AlignVCenter
      }

#### Indicator

      indicator: Rectangle {
          implicitWidth: 28
          implicitHeight: 28
          x: text ? (control.mirrored ? control.width - width - control.rightPadding : control.leftPadding) : control.leftPadding + (control.availableWidth - width) / 2
          y: control.topPadding + (control.availableHeight - height) / 2

          color: control.enabled ? (control.pressed ? "#e4e4e4" : "#f6f6f6") : "#353637"
          border.color: control.enabled ? (control.pressed ? "#26282a" : "#353637") : "transparent"

          Image {
              x: (parent.width - width) / 2
              y: (parent.height - height) / 2
              source: "qrc:/qt-project.org/imports/Qt/labs/controls/images/check.png"
              visible: control.checkState === Qt.Checked
          }

          Rectangle {
              x: (parent.width - width) / 2
              y: (parent.height - height) / 2
              width: 16
              height: 3
              color: "#353637"
              visible: control.checkState === Qt.PartiallyChecked
          }
      }

## Customizing ComboBox

ComboBox consists of background, content item, popup, and delegate.

#### Background

      background: Item {
          implicitWidth: 120
          implicitHeight: 40

          Rectangle {
              width: parent.width
              height: parent.height
              opacity: control.enabled ? 1.0 : 0.2
              color: control.pressed || popup.visible ? "#585A5C" : "#353637"
          }

          Image {
              x: parent.width - width - control.rightPadding
              y: (parent.height - height) / 2
              source: "qrc:/qt-project.org/imports/Qt/labs/controls/images/drop-indicator.png"
          }
      }

#### Content item

      contentItem: Text {
          text: control.displayText
          font: control.font
          color: "#ffffff"
          horizontalAlignment: Text.AlignLeft
          verticalAlignment: Text.AlignVCenter
          elide: Text.ElideRight
          rightPadding: 18 + control.spacing
      }

#### Popup

      popup: T.Popup {
          y: control.height - 1
          implicitWidth: control.width
          implicitHeight: listview.contentHeight
          topMargin: 6
          bottomMargin: 6

          contentItem: ListView {
              id: listview
              clip: true
              model: control.popup.visible ? control.delegateModel : null
              currentIndex: control.highlightedIndex

              Rectangle {
                  z: 10
                  parent: listview
                  width: listview.width
                  height: listview.height
                  border.color: "#353637"
                  color: "transparent"
              }

              T.ScrollIndicator.vertical: ScrollIndicator { }
          }

          background: Rectangle { }
      }

#### Delegate

      delegate: ItemDelegate {
          width: control.width
          text: control.textRole ? (Array.isArray(control.model) ? modelData[control.textRole] : model[control.textRole]) : modelData
          checkable: true
          autoExclusive: true
          checked: control.currentIndex === index
          highlighted: control.highlightedIndex === index
          pressed: highlighted && control.pressed
      }

## Customizing Dial

Dial consists of two visual items: background and handle.

#### Background

      background: Rectangle {
          x: control.width / 2 - width / 2
          y: control.height / 2 - height / 2
          width: Math.max(64, Math.min(control.width, control.height))
          height: Math.max(64, Math.min(control.width, control.height))
          radius: width / 2
          border.color: "#353637"
      }

#### Indicator

      handle: Image {
          id: handleItem
          x: background.x + background.width / 2 - handle.width / 2
          y: background.y + background.height / 2 - handle.height / 2
          width: 14
          height: 10
          source: "qrc:/qt-project.org/imports/Qt/labs/controls/images/dial-indicator.png"
          antialiasing: true
          transform: [
              Translate {
                  y: -background.height * 0.4 + handle.height / 2
              },
              Rotation {
                  angle: control.angle
                  origin.x: handle.width / 2
                  origin.y: handle.height / 2
              }
          ]
      }

## Customizing Drawer

Drawer can have a visual background item. The navigation is implemented by the content item.

#### Background

#### Content item

Drawer has no content item by default.

## Customizing Frame

Frame consists of two visual items: background and frame.

#### Background

Frame has no background item by default.

#### Frame

      frame: Rectangle {
          width: parent.width
          height: parent.height

          color: "transparent"
          border.color: "#bdbebf"
      }

## Customizing GroupBox

GroupBox consists of three visual items: background, frame and label.

#### Background

GroupBox has no background item by default.

#### Frame

      frame: Rectangle {
          y: control.topPadding - control.padding
          width: parent.width
          height: parent.height - control.topPadding + control.padding

          color: "transparent"
          border.color: "#bdbebf"
      }

#### Label

      label: Text {
          x: control.leftPadding
          width: control.availableWidth

          text: control.title
          font: control.font
          color: control.enabled ? "#353637" : "#bdbebf"
          elide: Text.ElideRight
          horizontalAlignment: Text.AlignLeft
          verticalAlignment: Text.AlignVCenter
      }

## Customizing ItemDelegate

ItemDelegate consists of three visual items: background, label and indicator. The indicator is only visible for checkable items.

#### Background

      background: Rectangle {
          implicitWidth: 100
          implicitHeight: 40
          visible: control.pressed || control.highlighted
          color: control.pressed ? "#bdbebf" : "#eeeeee"
      }

#### Label

      label: Text {
          x: control.mirrored ? control.width - width - control.rightPadding : control.leftPadding
          y: control.topPadding
          width: control.availableWidth - (control.checkable ? indicator.width + control.spacing : 0)
          height: control.availableHeight

          text: control.text
          font: control.font
          color: control.enabled ? "#26282a" : "#bdbebf"
          elide: Text.ElideRight
          visible: control.text
          horizontalAlignment: Text.AlignLeft
          verticalAlignment: Text.AlignVCenter
      }

#### Indicator

      indicator: Image {
          x: control.mirrored ? control.leftPadding : control.width - width - control.rightPadding
          y: control.topPadding + (control.availableHeight - height) / 2

          visible: control.checked
          source: control.checkable ? "qrc:/qt-project.org/imports/Qt/labs/controls/images/check.png" : ""
      }

## Customizing Label

Label can have a visual background item.

#### Background

Label has no background item by default.

## Customizing Menu

Menu consists of a contentItem.

#### Content item

      contentItem: ListView {
          implicitHeight: contentHeight
          model: control.contentModel
          // TODO: improve this?
          interactive: ApplicationWindow.window ? contentHeight > ApplicationWindow.window.height : false
          clip: true
          keyNavigationWraps: false
          currentIndex: -1

          ScrollIndicator.vertical: ScrollIndicator {}
      }

## Customizing MenuItem

MenuItem can be customized in the same manner as Button.

## Customizing PageIndicator

TODO

## Customizing Pane

Pane consists of a background.

#### Background

      background: Rectangle {
          color: "#ffffff"
      }

## Customizing ProgressBar

ProgressBar consists of two visual items: background and indicator.

#### Background

      background: Rectangle {
          implicitWidth: 200
          implicitHeight: 6
          x: control.leftPadding
          y: control.topPadding + (control.availableHeight - height) / 2
          width: control.availableWidth
          height: 6

          color: "#e4e4e4"
      }

#### Indicator

      indicator: ProgressStrip {
          id: strip
          x: control.leftPadding
          y: control.topPadding + (control.availableHeight - height) / 2
          width: control.availableWidth
          height: 6
          scale: control.mirrored ? -1 : 1
          progress: control.position
          indeterminate: control.indeterminate

          ProgressStripAnimator {
              target: strip
              running: control.visible && control.indeterminate
          }
      }

## Customizing RadioButton

RadioButton consists of three visual items: background, label and indicator.

#### Background

RadioButton has no background item by default.

#### Label

      label: Text {
          x: control.mirrored ? control.leftPadding : (indicator.x + indicator.width + control.spacing)
          y: control.topPadding
          width: control.availableWidth - indicator.width - control.spacing
          height: control.availableHeight

          text: control.text
          font: control.font
          color: control.pressed ? "#26282a" : "#353637"
          elide: Text.ElideRight
          visible: control.text
          horizontalAlignment: Text.AlignLeft
          verticalAlignment: Text.AlignVCenter
      }

#### Indicator

      indicator: Rectangle {
          implicitWidth: 28
          implicitHeight: 28
          x: text ? (control.mirrored ? control.width - width - control.rightPadding : control.leftPadding) : control.leftPadding + (control.availableWidth - width) / 2
          y: control.topPadding + (control.availableHeight - height) / 2

          radius: width / 2
          border.width: 1
          border.color: (control.pressed ? "#26282a" : "#353637")
          color: control.pressed ? "#e4e4e4" : "#f6f6f6"

          Rectangle {
              x: (parent.width - width) / 2
              y: (parent.height - height) / 2
              width: 20
              height: 20
              radius: width / 2
              color: control.pressed ? "#26282a" : "#353637"
              visible: control.checked
          }
      }

## Customizing RangeSlider

RangeSlider consists of four visual items: background, track, first.handle and second.handle.

#### Background

RangeSlider has no background item by default.

#### Track

      track: Rectangle {
          x: control.leftPadding + (horizontal ? 0 : (control.availableWidth - width) / 2)
          y: control.topPadding + (horizontal ? (control.availableHeight - height) / 2 : 0)
          implicitWidth: horizontal ? 200 : 6
          implicitHeight: horizontal ? 6 : 200
          width: horizontal ? control.availableWidth : implicitWidth
          height: horizontal ? implicitHeight : control.availableHeight
          radius: 3
          border.color: "#353637"
          color: "#ffffff"
          scale: horizontal && control.mirrored ? -1 : 1

          readonly property bool horizontal: control.orientation === Qt.Horizontal
      }

#### First Handle

      first.handle: Rectangle {
          x: control.leftPadding + (horizontal ? control.first.visualPosition * (control.availableWidth - width) : (control.availableWidth - width) / 2)
          y: control.topPadding + (horizontal ? (control.availableHeight - height) / 2 : control.first.visualPosition * (control.availableHeight - height))
          implicitWidth: 28
          implicitHeight: 28
          radius: width / 2
          border.width: activeFocus ? 2 : 1
          border.color: "#353637"
          color: first.pressed ? "#bdbebf" : "#ffffff"

          readonly property bool horizontal: control.orientation === Qt.Horizontal
      }

#### Second Handle

      second.handle: Rectangle {
          x: control.leftPadding + (horizontal ? control.second.visualPosition * (control.availableWidth - width) : (control.availableWidth - width) / 2)
          y: control.topPadding + (horizontal ? (control.availableHeight - height) / 2 : control.second.visualPosition * (control.availableHeight - height))
          implicitWidth: 28
          implicitHeight: 28
          radius: width / 2
          border.width: activeFocus ? 2 : 1
          border.color: "#353637"
          color: second.pressed ? "#bdbebf" : "#ffffff"

          readonly property bool horizontal: control.orientation === Qt.Horizontal
      }

## Customizing ScrollBar

ScrollBar consists of two visual items: background and handle.

#### Background

ScrollBar has no background item by default.

#### Handle

      handle: Rectangle {
          id: handle

          implicitWidth: 6
          implicitHeight: 6

          radius: width / 2
          color: control.pressed ? "#28282a" : "#bdbebf"
          visible: control.size < 1.0
          opacity: 0.0

          readonly property bool horizontal: control.orientation === Qt.Horizontal
          x: control.leftPadding + (horizontal ? control.position * control.availableWidth : 0)
          y: control.topPadding + (horizontal ? 0 : control.position * control.availableHeight)
          width: horizontal ? control.size * control.availableWidth : implicitWidth
          height: horizontal ? implicitHeight : control.size * control.availableHeight

          states: State {
              name: "active"
              when: control.active
              PropertyChanges { target: handle; opacity: 0.75 }
          }

          transitions: Transition {
              from: "active"
              SequentialAnimation {
                  PauseAnimation { duration: 450 }
                  NumberAnimation { target: handle; duration: 200; property: "opacity"; to: 0.0 }
              }
          }
      }

## Customizing ScrollIndicator

ScrollIndicator consists of two visual items: background and indicator.

#### Background

ScrollIndicator has no background item by default.

#### Indicator

      indicator: Rectangle {
          id: indicator

          implicitWidth: 2
          implicitHeight: 2

          color: "#bdbebf"
          visible: control.size < 1.0
          opacity: 0.0

          readonly property bool horizontal: control.orientation === Qt.Horizontal
          x: control.leftPadding + (horizontal ? control.position * control.width : 0)
          y: control.topPadding + (horizontal ? 0 : control.position * control.height)
          width: horizontal ? control.size * control.availableWidth : implicitWidth
          height: horizontal ? implicitHeight : control.size * control.availableHeight

          states: State {
              name: "active"
              when: control.active
              PropertyChanges { target: indicator; opacity: 0.75 }
          }

          transitions: [
              Transition {
                  from: "active"
                  SequentialAnimation {
                      PauseAnimation { duration: 450 }
                      NumberAnimation { target: indicator; duration: 200; property: "opacity"; to: 0.0 }
                  }
              }
          ]
      }

## Customizing Slider

Slider consists of three visual items: background, track and handle.

#### Background

Slider has no background item by default.

#### Track

      track: Rectangle {
          x: control.leftPadding + (horizontal ? 0 : (control.availableWidth - width) / 2)
          y: control.topPadding + (horizontal ? (control.availableHeight - height) / 2 : 0)
          implicitWidth: horizontal ? 200 : 6
          implicitHeight: horizontal ? 6 : 200
          width: horizontal ? control.availableWidth : implicitWidth
          height: horizontal ? implicitHeight : control.availableHeight
          radius: 3
          border.color: "#353637"
          color: "#ffffff"
          scale: horizontal && control.mirrored ? -1 : 1

          readonly property bool horizontal: control.orientation === Qt.Horizontal
      }

#### Handle

      handle: Rectangle {
          x: control.leftPadding + (horizontal ? control.visualPosition * (control.availableWidth - width) : (control.availableWidth - width) / 2)
          y: control.topPadding + (horizontal ? (control.availableHeight - height) / 2 : control.visualPosition * (control.availableHeight - height))
          implicitWidth: 28
          implicitHeight: 28
          radius: width / 2
          border.color: "#353637"
          color: control.pressed ? "#bdbebf" : "#f6f6f6"

          readonly property bool horizontal: control.orientation === Qt.Horizontal
      }

## Customizing SpinBox

SpinBox consists of four visual items: background, contentItem, up indicator, and down indicator.

#### Background

      background: Rectangle {
          implicitWidth: 140
          border.color: "#bdbebf"
      }

#### Content item

      contentItem: TextInput {
          text: control.textFromValue(control.value, control.locale)

          font: control.font
          color: "#353637"
          selectionColor: "#fddd5c"
          selectedTextColor: color
          horizontalAlignment: Qt.AlignHCenter
          verticalAlignment: Qt.AlignVCenter

          validator: control.validator
          inputMethodHints: Qt.ImhFormattedNumbersOnly
      }

#### Down indicator

      down.indicator: Rectangle {
          x: control.mirrored ? parent.width - width : 0
          height: parent.height
          implicitWidth: 40
          implicitHeight: 40
          color: down.pressed ? "#e4e4e4" : "#f6f6f6"
          border.color: control.enabled ? "#353637" : "#bdbebf"

          Rectangle {
              x: (parent.width - width) / 2
              y: (parent.height - height) / 2
              width: parent.width / 3
              height: 2
              color: control.enabled ? "#353637" : "#bdbebf"
          }
      }

#### Up indicator

      up.indicator: Rectangle {
          x: control.mirrored ? 0 : parent.width - width
          height: parent.height
          implicitWidth: 40
          implicitHeight: 40
          color: up.pressed ? "#e4e4e4" : "#f6f6f6"
          border.color: control.enabled ? "#353637" : "#bdbebf"

          Rectangle {
              x: (parent.width - width) / 2
              y: (parent.height - height) / 2
              width: parent.width / 3
              height: 2
              color: control.enabled ? "#353637" : "#bdbebf"
          }
          Rectangle {
              x: (parent.width - width) / 2
              y: (parent.height - height) / 2
              width: 2
              height: parent.width / 3
              color: control.enabled ? "#353637" : "#bdbebf"
          }
      }

## Customizing StackView

StackView can have a visual background item, and it allows customizing the transitions that are used for push, pop, and replace operations.

#### Push enter

      pushEnter: Transition {
          XAnimator { from: (root.mirrored ? -1 : 1) * root.width; to: 0; duration: 400; easing.type: Easing.OutCubic }
      }

#### Push exit

      pushExit: Transition {
          XAnimator { from: 0; to: (root.mirrored ? -1 : 1) * -root.width; duration: 400; easing.type: Easing.OutCubic }
      }

#### Pop enter

      popEnter: Transition {
          XAnimator { from: (root.mirrored ? -1 : 1) * -root.width; to: 0; duration: 400; easing.type: Easing.OutCubic }
      }

#### Pop exit

      popExit: Transition {
          XAnimator { from: 0; to: (root.mirrored ? -1 : 1) * root.width; duration: 400; easing.type: Easing.OutCubic }
      }

#### Replace enter

      replaceEnter: Transition {
          XAnimator { from: (root.mirrored ? -1 : 1) * root.width; to: 0; duration: 400; easing.type: Easing.OutCubic }
      }

#### Replace exit

      replaceExit: Transition {
          XAnimator { from: 0; to: (root.mirrored ? -1 : 1) * -root.width; duration: 400; easing.type: Easing.OutCubic }
      }

## Customizing SwipeView

SwipeView can have a visual background item. The navigation is implemented by the content item.

#### Background

SwipeView has no background item by default.

#### Content item

      contentItem: ListView {
          model: control.contentModel
          currentIndex: control.currentIndex

          spacing: control.spacing
          orientation: Qt.Horizontal
          snapMode: ListView.SnapOneItem
          boundsBehavior: Flickable.StopAtBounds

          highlightRangeMode: ListView.StrictlyEnforceRange
          preferredHighlightBegin: 0
          preferredHighlightEnd: 0
          highlightMoveDuration: 250
      }

## Customizing Switch

Switch consists of three visual items: background, label and indicator.

#### Background

Switch has no background item by default.

#### Label

      label: Text {
          x: control.mirrored ? control.leftPadding : (indicator.x + indicator.width + control.spacing)
          y: control.topPadding
          width: control.availableWidth - indicator.width - control.spacing
          height: control.availableHeight

          text: control.text
          font: control.font
          color: control.enabled ? "#26282a" : "#bdbebf"
          elide: Text.ElideRight
          visible: control.text
          horizontalAlignment: Text.AlignLeft
          verticalAlignment: Text.AlignVCenter
      }

#### Indicator

      indicator: Item {
          x: text ? (control.mirrored ? control.width - width - control.rightPadding : control.leftPadding) : control.leftPadding + (control.availableWidth - width) / 2
          y: control.topPadding + (control.availableHeight - height) / 2
          implicitWidth: 56
          implicitHeight: 28

          Rectangle {
              y: parent.height / 2 - height / 2
              width: 56
              height: 16
              radius: 8
              border.width: 1
              color: control.checked ? "#353637" : "transparent"
              border.color: control.checked ? "transparent" : "#353637"
          }

          Rectangle {
              x: Math.max(0, Math.min(parent.width - width, control.visualPosition * parent.width - (width / 2)))
              y: (parent.height - height) / 2
              width: 28
              height: 28
              radius: 16
              color: control.pressed ? "#e4e4e4" : "#f6f6f6"
              border.width: 1
              border.color: control.pressed ? "#26282a" : "#353637"

              Behavior on x {
                  enabled: !control.pressed
                  SmoothedAnimation { velocity: 200 }
              }
          }
      }

## Customizing TabBar

TODO

## Customizing TabButton

TODO

## Customizing TextArea

TODO

## Customizing TextField

TextField offers a customizable background item.

#### Background

      background: Rectangle {
          implicitWidth: 200
          implicitHeight: 40
      //        border.width: control.activeFocus ? 2 : 1
          color: control.enabled ? "transparent" : "#353637"
          border.color: control.enabled ? "#bdbebf" : "transparent"
      }

## Customizing ToolBar

ToolBar consists of two visual items: background and frame.

#### Background

      background: Rectangle {
          implicitHeight: 40
          color: "#eeeeee"
      }

#### Frame

ToolBar has no frame item by default.

## Customizing ToolButton

ToolButton consists of two visual items: background and label.

#### Background

      background: Rectangle {
          implicitWidth: 40
          implicitHeight: 40

          color: Qt.darker("#33333333", control.enabled && (control.checked || control.highlighted) ? 1.5 : 1.0)
          opacity: control.pressed ? 1.0 : control.enabled && (control.checked || control.highlighted) ? 0.5 : 0
          visible: control.pressed || (control.enabled && (control.checked || control.highlighted))
      }

#### Label

      label: Text {
          x: control.leftPadding
          y: control.topPadding
          width: control.availableWidth
          height: control.availableHeight

          text: control.text
          font: control.font
          color: control.enabled ? "#26282a" : "#c2c2c2"
          elide: Text.ElideRight
          horizontalAlignment: Text.AlignHCenter
          verticalAlignment: Text.AlignVCenter
      }

## Customizing Tumbler

Tumbler consists of three visual items: background, contentItem, and delegate.

#### Background

Tumbler has no background item by default.

#### Content Item

      contentItem: PathView {
          id: pathView
          model: control.model
          delegate: control.delegate
          clip: true
          pathItemCount: control.visibleItemCount + 1
          preferredHighlightBegin: 0.5
          preferredHighlightEnd: 0.5
          dragMargin: width / 2

          path: Path {
              startX: pathView.width / 2
              startY: -pathView.delegateHeight / 2
              PathLine {
                  x: pathView.width / 2
                  y: pathView.pathItemCount * pathView.delegateHeight - pathView.delegateHeight / 2
              }
          }

          property real delegateHeight: control.availableHeight / control.visibleItemCount
      }

#### Delegate

      delegate: Text {
          id: label
          text: modelData
          color: "#666666"
          font: control.font
          opacity: 0.4 + Math.max(0, 1 - Math.abs(Tumbler.displacement)) * 0.6
          horizontalAlignment: Text.AlignHCenter
          verticalAlignment: Text.AlignVCenter
      }