Tutorial: Qt Quick Application

This tutorial illustrates how to use Qt VS Tools to create a Qt Quick application. You will create a project using a project wizard and design a Qt Quick UI. In addition, you will learn how to add QML module definitions and QML files to your projects.

You can use Qt VS Tools to develop also Qt Widgets applications.

Before You Start

Before you start, you have to:

Create a Qt Quick Application Project

To create a Qt Quick application project in Visual Studio:

  1. Select File > New > Project, and search for Qt Quick Application.
  2. Select the project wizard, and then select Next.
  3. In the Project name field, enter QuickAddressBook, and then select Create.
  4. To acknowledge the Welcome dialog, select Next.
  5. To set up debug and release build configurations, click in Quick Modules, and select the Quick and Quick Controls2 modules to include in the project:

    "Selecting Qt modules in Qt Quick Application Wizard"

  6. Select Finish to create the project.

You now have a small working Qt Quick application. Select Build > Build Solution to build it, and then select Debug > Start Debugging to run it. For now, the result is an empty window.

Design the Main Window

The wizard created a main QML file for you, which declares a root object of the type Window. You can modify the file to design the application's main window.

Specify values for the Window color and title properties to set the background color and title of the application main window:

Window {
    id: mainWindow
    visible: true
    width: 480
    height: 640
    color: "darkgray"
    title: qsTr("Address Book")

Add a Button

To create the Add button, declare an object of the Button type from the Qt Quick Controls module. Set the value of the button text property to Add and the value of the font.pointSize property to 24:

        Button {
            id: addButton
            anchors.left: parent.left
            anchors.right: parent.right
            text: "Add..."
            font.pointSize: 24

When you run the application, you should now see this:

QuickAddressBook's main window

Connect the Button to an Action

QML has a signal and handler mechanism, where the signal is the event and the signal is responded to through a signal handler. When a signal is emitted, the corresponding signal handler is invoked. Placing logic such as a script or other operations in the handler allows the component to respond to the event.

To receive a notification when a particular signal is emitted for a particular object, the object definition should declare a signal handler named on<Signal>, where <Signal> is the name of the signal, with the first letter capitalized. The signal handler should contain the JavaScript code to be executed when the signal handler is invoked.

The Button type has a clicked signal, which is emitted when the users click the button. To invoke a popup for adding an address book entry when the users select the Add button in the main window, you must connect the onClicked signal handler of the button to the open() method of the popup. You will add the popup as a separate QML type later.

            onClicked: newAddressPopup.open()
        }

Add a List Model

QuickAddressBook entries

Within the Window, declare an object of the ListModel type with the id addressList for storing the contact data. A list model defines a free-form list data source:

    ListModel {
        id: addressList
    }

Declare a Popup

Declare an object of the custom NewAddressPopup type that defines the popup where the users will add address book entries. Use the onAddressAdded signal handler to determine that address book entries are appended to the addressList model:

    NewAddressPopup {
        id: newAddressPopup
        onAddressAdded: addressList.append({name: newName, addr: newAddr})
    }

You will create the NewAddressPopup type later.

Position the Button

Declare an object of ColumnLayout type to position the Button object and an instance of the Repeater type:

    ColumnLayout {
        id: mainWindowLayout
        anchors.left: parent.left; anchors.right: parent.right
        spacing: 0
        Button {
            id: addButton
            anchors.left: parent.left
            anchors.right: parent.right
            text: "Add..."
            font.pointSize: 24
            onClicked: newAddressPopup.open()
        }

Anchor the column layout to the left and right edges of its parent to make the application scalable on different screen sizes. Set the spacing between the rows in the column to 0.

Add a Repeater

The Repeater type is used to create a large number of similar items. It has a model and a delegate: for each entry in the model, the delegate is instantiated in a context seeded with data from the model. A repeater is usually enclosed in an instance of a positioner type such as a ColumnLayout to visually position the multiple delegate items created by the repeater.

Specify addressList as the model to use for the repeater:

        Repeater {
            id: addressListViewer
            model: addressList
            anchors.left: parent.left
            anchors.right: parent.right

Declare an object of the custom AddressBookItem type that the repeater will use to instantiate address book entries:

            AddressBookItem {
                id: addressBookItem

You will create the AddressBookItem type later.

Connect the Remove Button to an Action

Use the onRemoved signal handler to specify that an address book entry is removed from the list when the users click the Remove button for an address book entry.

                onRemoved: addressList.remove(index)
            }

Add a Popup

Now that the main window is ready, you can move on to create the popup where users can add address book entries. The data that the users enter is instantiated by the repeater in the main window, as specified by the AddressBookItem type.

QuickAddressBook's popup

You can use a Qt file wizard in Visual Studio to create a custom type that defines the popup.

To create custom QML types, you must first add a QML Module Definition (qmldir) file to the project.

Add a QML Module Definition

A QML module definition (qmldir) maps each custom QML type to its corresponding source file.

To add a QML module definition, select Project > Add New Item > Qt > Qt QML Module Definition > Add.

In the qmldir file, add QML type definitions for AddressBookItem and NewAddressPopup:

AddressBookItem    1.0    AddressBookItem.qml
NewAddressPopup    1.0    NewAddressPopup.qml

Next, you will create the QML types.

Create a Popup

To add a custom QML type to the project:

  1. Select Project > Add New File > Qt > Qt QML File > Add.
  2. In the Name field, enter NewAddressPopup.
  3. Select Finish to create a custom QML type.

Design the Popup

In NewAddressPopup.qml, declare a root object of the type Popup to create a popup that can be opened within a Window. A popup does not provide a layout of its own, so you will use a ColumnLayout and a RowLayout to position the Name and E-Mail Address fields.

Popup {
    id: newAddressPopup

Set the modal property to true to specify that the popup is modal. Set the focus property to true to specify that the popup requests focus:

    modal: true
    focus: true

Specify values for the width, x, and y properties to determine the position and size of the popup on top of the main window:

    width: parent.width * 0.9
    x: (parent.width - width) / 2
    y: 35

Reset Popup Controls

When the popup opens, the Name and E-Mail Address fields should display placeholder text and any values entered previously should be cleared. You use the onOpened signal handler to reset the values of the fields and give focus to the Name field:

    onOpened: {
        nameField.text = "";
        addrField.text = "";
        nameField.focus = true;
    }

Position Fields

Use an instance of the ColumnLayout type to position the TextField objects that specify the Name and E-Mail Address fields of the popup:

    ColumnLayout {
        anchors.fill: parent
        TextField {
            id: nameField
            placeholderText: qsTr("Name")
            font.pointSize: 24
            background: Rectangle { color: "lightgray" }
            Layout.preferredWidth: newAddressPopup / 2
            Layout.fillWidth: true
        }
        TextField {
            id: addrField
            placeholderText: qsTr("E-Mail Address")
            font.pointSize: 24
            background: Rectangle { color: "lightgray" }
            Layout.preferredWidth: newAddressPopup / 2
            Layout.fillWidth: true
        }

Position Buttons

Use an instance of a RowLayout type to position two Button objects that specify the Add and Cancel buttons:

        RowLayout {
            anchors.left: parent.left; anchors.right: parent.right
            Button {
                text: "Add"
                enabled: nameField.length > 0 && addrField.length > 0
                font.pointSize: 24
                Layout.preferredWidth: newAddressPopup / 2
                Layout.fillWidth: true

Connect Buttons to Actions

When the users click the Add button, the values they entered to the Name and E-Mail Address fields are added to the address list in the main window and the popup is closed.

To enable this, add the addressAdded(string newName, string newAddr) signal:

    signal addressAdded(string newName, string newAddr)

Connect the onClicked signal handler of the Add button to the addressAdded() signal and to the popup's close() method:

            Button {
                text: "Add"
                enabled: nameField.length > 0 && addrField.length > 0
                font.pointSize: 24
                Layout.preferredWidth: newAddressPopup / 2
                Layout.fillWidth: true
                onClicked: {
                    newAddressPopup.addressAdded(nameField.text, addrField.text)
                    newAddressPopup.close()
                }
            }

For the Cancel button, connect the onClicked signal handler to the to the popup's close() method to close the popup without saving the data:

            Button {
                text: "Cancel"
                font.pointSize: 24
                Layout.preferredWidth: newAddressPopup / 2
                Layout.fillWidth: true
                onClicked: newAddressPopup.close()
            }

Define an Address Book Entry

Address book entries are presented in the main window as specified by a custom AddressBookItem type.

Select Project > Add New File > Qt > Qt QML File > Add, to create a new QML file called AddressBookItem.qml.

Design the Entry

First, you will declare a root object of type Rectangle. It is one of the basic building blocks you can use to create an application in QML. Give it an id to be able to refer to it later.

Rectangle {
    id: addressBookItem

To use alternating colors for rows, set the value of the color property:

    color: (index % 2) == 0 ? "dimgray" : "lightgray"

Anchor the rectangle to the left and right edges of its parent to make the application scalable on different screen sizes. Bind the rectangle height property to the height of the text items it will contain:

    anchors.left: parent.left
    anchors.right: parent.right
    height: itemText.height + 12

Connect the Remove Button to an Action

Add the removed() signal that you will connect to the onClicked signal handler of the remove button. This removes an address book entry from the main window when users click the button:

    signal removed()

Position the Button and Text

Use instances of the RoundButton and Text types within an instance of a RowLayout type to define an address book entry:

    RowLayout {
        spacing: 12
        anchors.left: parent.left
        anchors.leftMargin: spacing
        RoundButton {
            id: deleteButton
            text: "🗙"
            font.pointSize: 12
            palette.buttonText: "red"
            onClicked: addressBookItem.removed()
        }

Format the Text

Set the value of the text property to combine the values of the name and addr fields from the popup and to use bold and italic formatting for the values:

        Text {
            id: itemText
            font.pointSize: 24
            text: "<b>" + name + "</b><br><i>" + addr + "</i>"
        }

Your application is now complete.

Create Project Files

To build the application on other platforms, you need to create a .pro file for the project, as instructed in Create Qt Project Files.

© 2022 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.