Qt 5.9 | Qt Quick Controls | Qt Quick Controls Examples | Qt Quick Controls - Touch Gallery

Qt 5.9.2 Reference Documentation

# Qt Quick Controls - Touch Gallery

Touch Gallery demonstrates how to implement a UI suitable for touch input using the following Qt Quick Controls:

- ApplicationWindow
- Button
- ProgressBar
- ScrollView
- Slider
- StackView
- Switch
- Tab
- TabView
- TextField

The appearance of the controls is customized by using Qt Quick Controls Styles.

## Running the Example

To run the example from Qt Creator, open the Welcome mode and select the example from Examples. For more information, visit Building and Running an Example.

## Creating the Main Page

In the main.qml file, we use a Rectangle type within the ApplicationWindow type to create the main page of the application:

      ApplicationWindow {
          visible: true
          width: 800
          height: 1280

          Rectangle {
              color: "#212126"
              anchors.fill: parent
          }

To use the Qt Quick Controls, we must import them:

      import QtQuick.Controls 1.2

The `toolBar` property of the application window holds a BorderImage type that we use to create a separator between the application name and a list of additional pages:

          toolBar: BorderImage {
              border.bottom: 8
              source: "images/toolbar.png"
              width: parent.width
              height: 100

We use an Image type in a Rectangle type to create a back button. We use the `onClicked` signal handler to call the StackView `pop()` function that pops off the page when users tap the button:

              Rectangle {
                  id: backButton
                  width: opacity ? 60 : 0
                  anchors.left: parent.left
                  anchors.leftMargin: 20
                  opacity: stackView.depth > 1 ? 1 : 0
                  anchors.verticalCenter: parent.verticalCenter
                  antialiasing: true
                  height: 60
                  radius: 4
                  color: backmouse.pressed ? "#222" : "transparent"
                  Behavior on opacity { NumberAnimation{} }
                  Image {
                      anchors.verticalCenter: parent.verticalCenter
                      source: "images/navigation_previous_item.png"
                  }
                  MouseArea {
                      id: backmouse
                      anchors.fill: parent
                      anchors.margins: -10
                      onClicked: stackView.pop()
                  }
              }

We use the `opacity` property to hide the back button on the main page.

We use a Text type to display the application name:

              Text {
                  font.pixelSize: 42
                  Behavior on x { NumberAnimation{ easing.type: Easing.OutCubic} }
                  x: backButton.x + backButton.width + 20
                  anchors.verticalCenter: parent.verticalCenter
                  color: "white"
                  text: "Widget Gallery"
              }

The `x` position of the Text type is bound to the position and width of the back button, and animated using a Behavior.

We use a ListModel type that contains ListElement definitions to define titles and source files for the other pages in the application:

          ListModel {
              id: pageModel
              ListElement {
                  title: "Buttons"
                  page: "content/ButtonPage.qml"
              }
              ListElement {
                  title: "Sliders"
                  page: "content/SliderPage.qml"
              }
              ListElement {
                  title: "ProgressBar"
                  page: "content/ProgressBarPage.qml"
              }
              ListElement {
                  title: "Tabs"
                  page: "content/TabBarPage.qml"
              }
              ListElement {
                  title: "TextInput"
                  page: "content/TextInputPage.qml"
              }
              ListElement {
                  title: "List"
                  page: "content/ListPage.qml"
              }
          }

## Navigating in the Application

We implement a stack-based navigation model to link the application pages together. Items are pushed onto the stack as users navigate deeper into the application, and popped off again when they return to the main page.

In main.qml, we add a StackView type as a child of the application window:

          StackView {
              id: stackView
              anchors.fill: parent
              // Implements back key navigation
              focus: true
              Keys.onReleased: if (event.key === Qt.Key_Back && stackView.depth > 1) {
                                   stackView.pop();
                                   event.accepted = true;
                               }

The stack is used by invoking its navigation methods. To load the first item in the stack view, we assign it to `initialItem`:

              initialItem: Item {
                  width: parent.width
                  height: parent.height
                  ListView {
                      model: pageModel
                      anchors.fill: parent
                      delegate: AndroidDelegate {
                          text: title
                          onClicked: stackView.push(Qt.resolvedUrl(page))
                      }
                  }
              }
          }

      }

We use a ListView type to display a list of the items provided by `pageModel`. The `AndroidDelegate` custom type defines each item instantiated by the view.

## Creating Push Buttons and Switches

In ButtonPage.qml we use the Button type to create two buttons that change color when users tap them and one that pops off the page and returns the user to the main page:

              Button {
                  text: "Press me"
                  style: touchStyle
              }

              Button {
                  style: touchStyle
                  text: "Press me too"
              }

              Button {
                  anchors.margins: 20
                  style: touchStyle
                  text: "Don't press me"
                  onClicked: if (stackView) stackView.pop()
              }

We use a Switch type to create two switches that users can turn on and off. They are placed within a Row type to lay them out horizontally:

              Row {
                  spacing: 20
                  Switch {
                      style: switchStyle
                  }
                  Switch {
                      style: switchStyle
                  }
              }

A ButtonStyle type creates a custom appearance for the buttons:

          Component {
              id: touchStyle
              ButtonStyle {
                  panel: Item {
                      implicitHeight: 50
                      implicitWidth: 320
                      BorderImage {
                          anchors.fill: parent
                          antialiasing: true
                          border.bottom: 8
                          border.top: 8
                          border.left: 8
                          border.right: 8
                          anchors.margins: control.pressed ? -4 : 0
                          source: control.pressed ? "../images/button_pressed.png" : "../images/button_default.png"
                          Text {
                              text: control.text
                              anchors.centerIn: parent
                              color: "white"
                              font.pixelSize: 23
                              renderType: Text.NativeRendering
                          }

To use Qt Quick Controls Styles, we must import them:

      import QtQuick.Controls.Styles 1.1

A SwitchStyle type creates a custom appearance for the switches:

          Component {
              id: switchStyle
              SwitchStyle {

                  groove: Rectangle {
                      implicitHeight: 50
                      implicitWidth: 152
                      Rectangle {
                          anchors.top: parent.top
                          anchors.left: parent.left
                          anchors.bottom: parent.bottom
                          width: parent.width/2 - 2
                          height: 20
                          anchors.margins: 2
                          color: control.checked ? "#468bb7" : "#222"
                          Behavior on color {ColorAnimation {}}
                          Text {
                              font.pixelSize: 23
                              color: "white"
                              anchors.centerIn: parent
                              text: "ON"
                          }
                      }
                      Item {
                          width: parent.width/2
                          height: parent.height
                          anchors.right: parent.right
                          Text {
                              font.pixelSize: 23
                              color: "white"
                              anchors.centerIn: parent
                              text: "OFF"
                          }
                      }
                      color: "#222"
                      border.color: "#444"
                      border.width: 2
                  }
                  handle: Rectangle {
                      width: parent.parent.width/2
                      height: control.height
                      color: "#444"
                      border.color: "#555"
                      border.width: 2
                  }
              }
          }
      }

The `groove` property holds the background groove of the switch and the `handle` property defines the switch handle.

## Creating Sliders

In SliderPage.qml, we use a Slider type to create three horizontal sliders that are placed within a Column type to lay them out in a column:

          Column {
              spacing: 12
              anchors.centerIn: parent

              Slider {
                  anchors.margins: 20
                  style: touchStyle
                  value: 0
              }
              Slider {
                  anchors.margins: 20
                  style: touchStyle
                  value: 0.5
              }
              Slider {
                  anchors.margins: 20
                  style: touchStyle
                  value: 1.0
              }

          }

The `value` property holds the initial handle position on the slider.

A SliderStyle type creates a custom appearance for the sliders:

          Component {
              id: touchStyle
              SliderStyle {
                  handle: Rectangle {
                      width: 30
                      height: 30
                      radius: height
                      antialiasing: true
                      color: Qt.lighter("#468bb7", 1.2)
                  }

                  groove: Item {
                      implicitHeight: 50
                      implicitWidth: 400
                      Rectangle {
                          height: 8
                          width: parent.width
                          anchors.verticalCenter: parent.verticalCenter
                          color: "#444"
                          opacity: 0.8
                          Rectangle {
                              antialiasing: true
                              radius: 1
                              color: "#468bb7"
                              height: parent.height
                              width: parent.width * control.value / control.maximumValue
                          }
                      }
                  }
              }
          }
      }

The `handle` property defines the slider handle and the `groove` property holds the background groove of the slider.

## Indicating Progress

In ProgressBar.qml, we use a ProgressBar type to create three progress bars:

          Column {
              spacing: 40
              anchors.centerIn: parent

              ProgressBar {
                  anchors.margins: 20
                  style: touchStyle
                  width: 400
                  value: progress
              }

              ProgressBar {
                  anchors.margins: 20
                  style: touchStyle
                  width: 400
                  value: 1 - progress
              }

              ProgressBar {
                  anchors.margins: 20
                  style: touchStyle
                  value: 1
                  width: 400
              }

We use a NumberAnimation type with a SequentialAnimation type to run two number animations in a sequence. We apply the animations on the `progress` custom property to animate the current value on the progress bars:

          property real progress: 0
          SequentialAnimation on progress {
              loops: Animation.Infinite
              running: true
              NumberAnimation {
                  from: 0
                  to: 1
                  duration: 3000
              }
              NumberAnimation {
                  from: 1
                  to: 0
                  duration: 3000
              }

A ProgressBarStyle type creates a custom appearance for the progress bars:

          Component {
              id: touchStyle
              ProgressBarStyle {
                  panel: Rectangle {
                      implicitHeight: 15
                      implicitWidth: 400
                      color: "#444"
                      opacity: 0.8
                      Rectangle {
                          antialiasing: true
                          radius: 1
                          color: "#468bb7"
                          height: parent.height
                          width: parent.width * control.value / control.maximumValue
                      }
                  }
              }
          }
      }

## Creating Tabs

In TabBarPage.qml, we use a TabView type with a Tab type to provide a tab-based navigation model for our application. We use tabs to display the ButtonPage, SliderPage, and ProgressBarPage on separate tab pages:

          TabView {
              anchors.fill: parent
              style: touchStyle
              Tab {
                  title: "Buttons"
                  ButtonPage{ visible: true }
              }
              Tab {
                  title: "Sliders"
                  SliderPage{ visible: true }
              }
              Tab {
                  title: "Progress"
                  ProgressBarPage{ visible: true }
              }

A TabViewStyle type creates a custom appearance for the tabs:

          Component {
              id: touchStyle
              TabViewStyle {
                  tabsAlignment: Qt.AlignVCenter
                  tabOverlap: 0
                  frame: Item { }
                  tab: Item {
                      implicitWidth: control.width/control.count
                      implicitHeight: 50
                      BorderImage {
                          anchors.fill: parent
                          border.bottom: 8
                          border.top: 8
                          source: styleData.selected ? "../images/tab_selected.png":"../images/tabs_standard.png"
                          Text {
                              anchors.centerIn: parent
                              color: "white"
                              text: styleData.title.toUpperCase()
                              font.pixelSize: 16
                          }
                          Rectangle {
                              visible: index > 0
                              anchors.top: parent.top
                              anchors.bottom: parent.bottom
                              anchors.margins: 10
                              width:1
                              color: "#3a3a3a"
                          }
                      }
                  }
              }
          }
      }

## Creating Text Input Fields

In the TextInputPage.qml, we use a TextField type to create an input field and a read-only text field:

          Column {
              spacing: 40
              anchors.centerIn: parent

              TextField {
                  anchors.margins: 20
                  text: "Text input"
                  style: touchStyle
              }

              TextField {
                  anchors.margins: 20
                  text: "Readonly Text input"
                  style: touchStyle
                  readOnly: true
              }
          }

A TextFieldStyle creates a custom appearance for the text fields:

          Component {
              id: touchStyle

              TextFieldStyle {
                  textColor: "white"
                  font.pixelSize: 28
                  background: Item {
                      implicitHeight: 50
                      implicitWidth: 320
                      BorderImage {
                          source: "../images/textinput.png"
                          border.left: 8
                          border.right: 8
                          anchors.bottom: parent.bottom
                          anchors.left: parent.left
                          anchors.right: parent.right
                      }
                  }
              }
          }
      }

We use a BorderImage type with an image to create borders for the fields.

## Creating Scrolling Lists

In ListPage.qml, we use a ScrollView type to provide a scrolling page with a vertical scoll bar:

      ScrollView {
          width: parent.width
          height: parent.height

          flickableItem.interactive: true

We use a ListView type to display a list of 100 items by specifying an integer as the value of the `model` property. We reuse the `AndroidDelegate` custom type here to define each item instantiated by the view. The `text` property adds the string `Item #` to each list item:

          ListView {
              anchors.fill: parent
              model: 100
              delegate: AndroidDelegate {
                  text: "Item #" + modelData
              }
          }

A ScrollViewStyle type creates a custom appearance for the scroll view:

          style: ScrollViewStyle {
              transientScrollBars: true
              handle: Item {
                  implicitWidth: 14
                  implicitHeight: 26
                  Rectangle {
                      color: "#424246"
                      anchors.fill: parent
                      anchors.topMargin: 6
                      anchors.leftMargin: 4
                      anchors.rightMargin: 4
                      anchors.bottomMargin: 6
                  }
              }
              scrollBarBackground: Item {
                  implicitWidth: 14
                  implicitHeight: 26
              }
          }
      }

The `transientScrollBars` property is set to `true` to make the scroll bars appear when the content is scrolled and disappear when they are no longer needed.

The `handle` property controls the appearance of the scroll bar handle and the `scrollBarBackground` property that of the background.

Files:

- touch/main.qml
- touch/content/AndroidDelegate.qml
- touch/content/ButtonPage.qml
- touch/content/ListPage.qml
- touch/content/ProgressBarPage.qml
- touch/content/SliderPage.qml
- touch/content/TabBarPage.qml
- touch/content/TextInputPage.qml
- touch/src/main.cpp
- touch/resources.qrc
- touch/touch.pro
- touch/touch.qmlproject

Images:

- touch/images/button_default.png
- touch/images/button_pressed.png
- touch/images/navigation_next_item.png
- touch/images/navigation_previous_item.png
- touch/images/tab_selected.png
- touch/images/tabs_standard.png
- touch/images/textinput.png
- touch/images/toolbar.png