Створення аркушів-накладок

Знайомимося із накладними аркушами.

Робимо нашу програму корисною

У нас є вікно, у нас є картки і у нас є дії. Але нам усе ще потрібне спосіб введення назви, опису та вибраної дати.

Одним зі способів досягти потрібного результату є створення сторінки, на якій ми розташуємо потрібні нам елементи для введення даних. Втім, надавати цілу сторінку для введення назви, опис та дати забагато.

Замість цього, ми використовуватимемо аркуш-накладку.

Аркуш-накладка, що з'являється посередині вікна програми як діалогове вікно

Аркуш додавання відліку

Новим доданим нами компонентом є Kirigami.OverlaySheet . Аркуші-накладки розташовуються над вмістом вікна. Ними можна скористатися для виконання багатьох завдань, зокрема надання додаткових відомостей, пов'язаних із поточним вмістом вікна. Вони є типом красивих контекстних вікон, але їх не можна пересувати.

Kirigami.OverlaySheet {
    id: addSheet
    header: Kirigami.Heading {
        text: i18nc("@title:window", "Add kountdown")
    }
    Kirigami.FormLayout {
        Controls.TextField {
            id: nameField
            Kirigami.FormData.label: i18nc("@label:textbox", "Name:")
            placeholderText: i18n("Event name (required)")
            onAccepted: descriptionField.forceActiveFocus()
        }
        Controls.TextField {
            id: descriptionField
            Kirigami.FormData.label: i18nc("@label:textbox", "Description:")
            placeholderText: i18n("Optional")
            onAccepted: dateField.forceActiveFocus()
        }
        Controls.TextField {
            id: dateField
            Kirigami.FormData.label: i18nc("@label:textbox", "Date:")
            placeholderText: i18n("YYYY-MM-DD")
            inputMask: "0000-00-00"
        }
        Controls.Button {
            id: doneButton
            Layout.fillWidth: true
            text: i18nc("@action:button", "Done")
            enabled: nameField.text.length > 0
            onClicked: {
                kountdownModel.append({
                    name: nameField.text,
                    description: descriptionField.text,
                    // Метод parse() обробляє рядок і повертає кількість мілісекунд з моменту часу 1
                    // січня 1970 року, 00:00:00 UTC.
                    date: Date.parse(dateField.text)
                });
                nameField.text = ""
                descriptionField.text = ""
                dateField.text = ""
                addSheet.close();
            }
        }
    }
}

Для аркушів-накладок можна визначати заголовки. Заголовки визначаються властивістю ` header . Ми надали цій властивості у нашому випадку значення Kirigami.Heading , які містить відповідний заголовок: «Add Kountdown».

Далі, ми переходимо до Kirigami.FormLayout . Цей об'єкт надає нам змогу без проблем створювати форми для введення даних, які раціонально показують мітки для полів введення та самі поля введення на широкоекранних дисплеях комп'ютерів та вузьких дисплеях мобільних пристроїв. Ці компонування форм розроблено для роботи із різними типами полів введення, хоча тут ми використовуємо прості поля Controls.Textfield , якщо відповідають простим текстовим блоками для вписування простих текстових фрагментів.

Нами створено елементи Textfield, які працюють як:

  1. Поле для введення назви нашого відліку
  2. Поле для введення опису нашого відліку
  3. Поле для введення дати, до якої ми ведемо відлік і яка надається у форматі YYYY-MM-DD.

У кожному з цих елементів Controls.Textfield ми встановлюємо значення властивості Kirigami.FormData.label , яка надає нам змогу визначити мітки для елементів. Форма покаже належні мітки ліворуч від кожного з цих текстових полів введення. Ми також визначаємо текст-замінник у полях за допомогою властивості TextField.placeholderText — цей текст зникне, щойно користувач почне вводити текст у поле. Нарешті, ми встановлюємо значення властивості onAccepted для вмикання методу forceActiveFocus() наступного поля; ця властивість перемкне активне поле, щойно користувач натисне клавішу ENTER. Така поведінка робить користування формою зручнішим.

Ми також встановлюємо для текстового поля для нашої дати властивість із назвою inputMask. Встановлення значення "0000-00-00" забороняє користувачеві вводити будь-що, що може зашкодити нормальній роботі програми (наприклад, звичайний текст). Користувач зможе вводити лише цифри, які згодом може бути перетворено на об'єкт дати.

Наприкінці нашої форми ми включаємо кнопку , яка додає новий відлік до моделі списку. Ми встановили для властивості enabled умовну інструкцію, яка перевіряє, чи є поле назви порожнім: якщо це так, кнопку буде вимкнено, і навпаки. Якщо кнопку увімкнено, вона вмикає метод append нашої моделі списку kountdownModel, додаючи об'єкт Javascript, включно із наданими нами властивостями. Крім того, ми спорожнюємо текстові поля, встановлюючи для їхні властивостей text порожні рядки. Нарешті, ми викликаємо метод для нашого аркуша-наклади, close() , який закриває його.

Використання нашого аркуша

actions.main: Kirigami.Action {
    id: addAction
    icon.name: "list-add"
    text: i18nc("@action:button", "Add kountdown")
    onTriggered: addSheet.open()
}

Для аркушів-накладок передбачено два методи, open() і close() , які керують відкриттям і закриттям цього компонента. У цьому випадку, ми встановили, що аркуш буде відкрито, коли ми увімкнемо нашу дію. Щойно наші файли буде збережено, а програму буде зібрано, ми зможемо додавати наші власні нетипові відліки!

Наша програма на поточний момент

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
import QtQuick 2.15
import QtQuick.Controls 2.15 as Controls
import QtQuick.Layouts 1.15
import org.kde.kirigami 2.20 as Kirigami

Kirigami.ApplicationWindow {
    id: root

    title: i18nc("@title:window", "Day Kountdown")

    globalDrawer: Kirigami.GlobalDrawer {
        isMenu: true
        actions: [
            Kirigami.Action {
                text: i18n("Quit")
                icon.name: "gtk-quit"
                shortcut: StandardKey.Quit
                onTriggered: Qt.quit()
            }
        ]
    }

    ListModel {
        id: kountdownModel
    }

    Component {
        id: kountdownDelegate
        Kirigami.AbstractCard {
            contentItem: Item {
                implicitWidth: delegateLayout.implicitWidth
                implicitHeight: delegateLayout.implicitHeight
                GridLayout {
                    id: delegateLayout
                    anchors {
                        left: parent.left
                        top: parent.top
                        right: parent.right
                    }
                    rowSpacing: Kirigami.Units.largeSpacing
                    columnSpacing: Kirigami.Units.largeSpacing
                    columns: root.wideScreen ? 4 : 2

                    Kirigami.Heading {
                        Layout.fillHeight: true
                        level: 1
                        text: i18n("%1 days", Math.round((date-Date.now())/86400000))
                    }

                    ColumnLayout {
                        Kirigami.Heading {
                            Layout.fillWidth: true
                            level: 2
                            text: name
                        }
                        Kirigami.Separator {
                            Layout.fillWidth: true
                            visible: description.length > 0
                        }
                        Controls.Label {
                            Layout.fillWidth: true
                            wrapMode: Text.WordWrap
                            text: description
                            visible: description.length > 0
                        }
                    }
                    Controls.Button {
                        Layout.alignment: Qt.AlignRight
                        Layout.columnSpan: 2
                        text: i18n("Edit")
                    }
                }
            }
        }
    }

    // Overlay sheets appear over a part of the window
    Kirigami.OverlaySheet {
        id: addSheet
        header: Kirigami.Heading {
            text: i18nc("@title:window", "Add kountdown")
        }
        // Form layouts help align and structure a layout with several inputs
        Kirigami.FormLayout {
            // Textfields let you input text in a thin textbox
            Controls.TextField {
                id: nameField
                // Provides label attached to the textfield
                Kirigami.FormData.label: i18nc("@label:textbox", "Name:")
                // Placeholder text is visible before you enter anything
                placeholderText: i18n("Event name (required)")
                // What to do after input is accepted (i.e. pressed enter)
                // In this case, it moves the focus to the next field
                onAccepted: descriptionField.forceActiveFocus()
            }
            Controls.TextField {
                id: descriptionField
                Kirigami.FormData.label: i18nc("@label:textbox", "Description:")
                placeholderText: i18n("Optional")
                onAccepted: dateField.forceActiveFocus()
            }
            Controls.TextField {
                id: dateField
                Kirigami.FormData.label: i18nc("@label:textbox", "Date:")
                placeholderText: i18n("YYYY-MM-DD")
                inputMask: "0000-00-00"
            }
            Controls.Button {
                id: doneButton
                Layout.fillWidth: true
                text: i18nc("@action:button", "Done")
                // Button is only enabled if the user has entered something into the nameField
                enabled: nameField.text.length > 0
                onClicked: {
                    // Add a listelement to the kountdownModel ListModel
                    kountdownModel.append({
                        name: nameField.text,
                        description: descriptionField.text,
                        date: Date.parse(dateField.text)
                    });
                    nameField.text = ""
                    descriptionField.text = ""
                    dateField.text = ""
                    addSheet.close();
                }
            }
        }
    }

    pageStack.initialPage: Kirigami.ScrollablePage {
        title: i18nc("@title", "Kountdown")

        // Kirigami.Action encapsulates a UI action. Inherits from Controls.Action
        actions.main: Kirigami.Action {
            id: addAction
            // Name of icon associated with the action
            icon.name: "list-add"
            // Action text, i18n function returns translated string
            text: i18nc("@action:button", "Add kountdown")
            // What to do when triggering the action
            onTriggered: addSheet.open()
        }

        Kirigami.CardsListView {
            id: layout
            model: kountdownModel
            delegate: kountdownDelegate
        }
    }
}

Знімок вікна програми з чотирма картками-прикладами