Getting Started with QML

This tutorial shows how to develop a simple alarm application as an introduction to QML and Qt Quick Controls. Until 5.11 the documentation did have an example "Getting Started Programming with Qt Quick", but that was not really written for someone who is a complete beginner in QML, nor did it use Qt Quick Controls.

The example is available in 5.12 and can be found here: Getting Started Programming with Qt Quick.

This is a simple app where the main screen is a ListView, and where most fields are filled using the Tumbler QML type. The app stores the alarms in a ListModel. The application is very similar to the alarm application usually found on an Android or IOS phone.

User Interface

The main screen shows the list of saved alarms:

mainscreen

The detail screen becomes visible when you click a particular alarm. It lets you edit or delete existing alarms. You can also select days on which the alarm needs to be repeated.

detailscreen

The dialog screen is used for adding new alarms. It pops up when you click on the "+" RoundButton on the bottom of the main screen:

addalarms

 

Entering and Saving Alarms

Most data is entered with the Tumbler QML type. Below you can see part of AlarmDialog.qml, the dialog for entering new alarms.qml.

    contentItem: RowLayout {
        RowLayout {
            id: rowTumbler
            Tumbler {
                id: hoursTumbler
                model: 24
                delegate: TumblerDelegate {
                    text: formatNumber(modelData)
                }
            }
            Tumbler {
                id: minutesTumbler
                model: 60
                delegate: TumblerDelegate {
                    text: formatNumber(modelData)
                }
            }
        }

RowLayout { id: datePicker

Layout.leftMargin: 20

property alias dayTumbler: dayTumbler property alias monthTumbler: monthTumbler property alias yearTumbler: yearTumbler

readonly property var days: [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]

Tumbler { id: dayTumbler

function updateModel() { // Populate the model with days of the month. For example: [0, ..., 30] var previousIndex = dayTumbler.currentIndex var array = [] var newDays = datePicker.days[monthTumbler.currentIndex] for (var i = 1; i <= newDays; ++i) array.push(i) dayTumbler.model = array dayTumbler.currentIndex = Math.min(newDays - 1, previousIndex) }

Component.onCompleted: updateModel()

delegate: TumblerDelegate { text: formatNumber(modelData) } } Tumbler { id: monthTumbler

onCurrentIndexChanged: dayTumbler.updateModel()

model: 12 delegate: TumblerDelegate { text: window.locale.standaloneMonthName(modelData, Locale.ShortFormat) } } Tumbler { id: yearTumbler

// This array is populated with the next three years. For example: [2018, 2019, 2020] readonly property var years: (function() { var currentYear = new Date().getFullYear() return [0, 1, 2].map(function(value) { return value + currentYear; }) })()

model: years delegate: TumblerDelegate { text: formatNumber(modelData) } } } }

Clicking on "OK" adds the new alarm to the ListModel with id alarmModel.

    onAccepted: {
        alarmModel.append({
            "hour": hoursTumbler.currentIndex,
            "minute": minutesTumbler.currentIndex,
            "day": dayTumbler.currentIndex + 1,
            "month": monthTumbler.currentIndex + 1,
            "year": yearTumbler.years[yearTumbler.currentIndex],
            "activated": true,
            "label": "",
            "repeat": false,
            "daysToRepeat": [
                { "dayOfWeek": 0, "repeat": false },
                { "dayOfWeek": 1, "repeat": false },
                { "dayOfWeek": 2, "repeat": false },
                { "dayOfWeek": 3, "repeat": false },
                { "dayOfWeek": 4, "repeat": false },
                { "dayOfWeek": 5, "repeat": false },
                { "dayOfWeek": 6, "repeat": false }
            ],
        })
    }

Some notes...

The program handles only the user interface and the ListModel that is storing the alarms. There is no code for storing the alarms physically in JSON format or SQLite, nor for the actual triggering of the alarm with sound or a popup window. Maybe that would be a nice challenge for someone starting with QML.


Blog Topics:

Comments