Dodajanje pogovornega okna
Izdelava naše aplikacije uporabne
Imamo okno, kartice in akcije. Vendar moramo še vedno najti način vnosa imena, opisa in datuma po naši izbiri.
To lahko storimo tako, da ustvarimo novo stran, kjer postavimo zahtevane vhodne elemente. Vendar pa se zdi cela stran, namenjena zagotavljanju imena, opisa in datuma, nekoliko pretirana.
Namesto tega bomo uporabili pogovorno okno.
Odpiranje pogovornega okna
pageStack.initialPage: Kirigami.ScrollablePage {
// ...
actions: [
Kirigami.Action {
id: addAction
icon.name: "list-add"
text: i18nc("@action:button", "Add kountdown")
onTriggered: addDialog.open()
}
]
}
First we edit the action from the previous tutorial: just a Kirigami.Action that triggers the dialog's open() function.
Pogovorna okna za dodajanje odštevanja
The new component we add is a Kirigami.Dialog. Dialogs appear at the center of the window and can be used to provide extra information relevant to the current content. They can't be moved, but they adapt their own size to the window.
Kirigami.ApplicationWindow {
// ...
Kirigami.Dialog {
id: addDialog
title: i18nc("@title:window", "Add kountdown")
standardButtons: Kirigami.Dialog.Ok | Kirigami.Dialog.Cancel
padding: Kirigami.Units.largeSpacing
preferredWidth: Kirigami.Units.gridUnit * 20
// Postavitve obrazcev pomagajo uskladiti in strukturirati postavitev z več vnosi
Kirigami.FormLayout {
// Textfields vam omogočajo vnos besedila v tanko besedilno polje
Controls.TextField {
id: nameField
// Zagotavlja oznako, pripeto besedilnemu polju
Kirigami.FormData.label: i18nc("@label:textbox", "Name*:")
// Kaj storiti, ko je vnos sprejet (tj. pritisnjen Enter) V tem primeru premakne
// fokus na naslednje polje
onAccepted: descriptionField.forceActiveFocus()
}
Controls.TextField {
id: descriptionField
Kirigami.FormData.label: i18nc("@label:textbox", "Description:")
placeholderText: i18n("Optional")
// Spet premakne fokus na naslednje polje
onAccepted: dateField.forceActiveFocus()
}
Controls.TextField {
id: dateField
Kirigami.FormData.label: i18nc("@label:textbox", "ISO Date*:")
// D pomeni zahtevano število med 1-9, 9 pomeni zahtevano število med 0-9
inputMask: "D999-99-99"
// Tukaj potrdimo operacijo tako kot s klikom na gumb V redu
onAccepted: addDialog.onAccepted()
}
Controls.Label {
text: "* = required fields"
}
}
// Logika dialoga gre sem
}
// ...
}
Pogovorna okna imajo privzeto glavo header in nogo [footer](https://doc.qt .io/qt-6/qml-qtquick-controls-dialog.html#footer-prop), oba podedovana iz Controls.Dialog.
The header by default includes a title and a close button that can be disabled with showCloseButton. The footer by default includes a close button, and it can be overridden with standardButtons.
We first set it to show an "Ok" button and a "Cancel" button, add some padding, and add a reasonable preferredWidth. The preferred width is the default expected size of the dialog, which can increase if needed. We can use standard Kirigami.Units that we will revisit later on.
Then we come to a Kirigami.FormLayout. Unlike a ColumnLayout, the layout of its child components is automatic and centered, with optional labels. As the name implies, it is used to create input forms.
Te postavitve obrazcev so zasnovane tako, da delujejo z različnimi vrstami vnosa, čeprav se držimo preprostih vnosov Controls.Textfield, ki nam dajejo preprosta besedilna polja, v katera lahko pišemo stvari.
Ustvarili smo elemente Textfield, ki delujejo kot:
- Vnos za ime našega odštevanja
- Vnos za opis našega odštevanja
- Vnos za datum, ki ga odštevamo proti vrednosti, ki jo je treba navesti v formatu 'YYYY-MM-DD'
Within each of these Controls.Textfield elements, we are setting a Kirigami.FormData.label property that lets us define labels for them. The form will present the correct labels to the left of each of these text input fields.
Nazadnje nastavimo tudi lastnost onAccepted, da sproži [forceActiveFocus()](https:/ /doc.qt.io/qt-6/qml-qtquick-item.html#forceActiveFocus-method) metodo naslednjega polja; to bo preklopilo aktivno polje, ko uporabnik pritisne tipko ENTER, kar izboljša uporabnost obrazca.
Prav tako smo nastavili lastnost z imenom inputMask v besedilnem polju za naš datum. Če to nastavite na D999-99-99
, preprečite uporabnikom, da bi vnesli nekaj, kar bi lahko pokvarilo funkcionalnost aplikacije (kot je besedilo), in jih omejite na vnos samo številk, ki jih lahko nato poskusimo razčleniti v objekt datuma.
Ko je uporabniški vmesnik za pogovorno okno končan, moramo spremeniti njegovo obnašanje. Za to potrebujemo tri stvari:
- Pokaži gumb V redu samo, ko so izpolnjena zahtevana polja
- Dodajte vhodne informacije v model
- Počistite obrazec za vnos
Kirigami.Dialog {
// ... Ko je Kirigami.Dialog inicializiran, želimo ustvariti vezavo po meri, da bo gumb V redu
// viden le, če so izpolnjena zahtevana besedilna polja. Za to uporabljamo
// Kirigami.Dialog.standardButton(button):
Component.onCompleted: {
const button = standardButton(Kirigami.Dialog.Ok);
// () => je funkcija JavaScript puščice
button.enabled = Qt.binding( () => requiredFieldsFilled() );
}
onAccepted: {
// Vezava je ustvarjena, vendar moramo še vedno onemogočiti klikanje, razen če so polja
// izpolnjena
if (!addDialog.requiredFieldsFilled()) return;
appendDataToModel();
clearFieldsAndClose();
}
}
Prva stvar, ki jo je treba narediti, je ustvariti povezavo med lastnostjo enabled gumba OK in preverjanje, ali so polja izpolnjena, kar je v tem primeru treba narediti s [Qt.binding()]Qt.binding() v JavaScript. Dejansko je vrstica:
button.enabled = Qt.binding( () => requiredFieldsFilled() );
podobna vezavam QML, ki smo jih videli do sedaj, kot v naslednji psevdo kodi:
enabled: requiredFieldsFilled()
Upravljalnik signalov, ki sproži gumb V redu, je onAccepted. Če so zahtevana polja izpolnjena, ostane prazen in ne naredi ničesar; v nasprotnem primeru bo dodal vnos v model in počistil pogovorno okno za naslednje odprtje.
Kirigami.Dialog {
// ... Preverimo, da nameField ni prazno in da je dateField (ki ima inputMask) v celoti
// izpolnjeno
function requiredFieldsFilled() {
return (nameField.text !== "" && dateField.acceptableInput);
}
function appendDataToModel() {
kountdownModel.append({
name: nameField.text,
description: descriptionField.text,
date: new Date(dateField.text)
});
}
function clearFieldsAndClose() {
nameField.text = ""
descriptionField.text = ""
dateField.text = ""
addDialog.close();
}
}
Za naše zahtevano polje z imenom moramo le preveriti, ali je besedilo polja prazen niz. Ker ima polje z datumom vnosno masko, moramo namesto tega uporabiti acceptableInput, kar samo postane true, ko je celotno polje izpolnjeno in vsebuje samo sprejemljive znake.
Nato metoda append() našega modela seznama kountdownModel
doda objekt JavaScript, ki vključuje lastnosti, ki smo jih zagotovili.
Na koncu poskrbimo, da počistimo besedilna polja tako, da nastavimo njihove lastnosti text na prazen niz, nato ga zapremo s close().
Ko shranimo svoje datoteke in zgradimo svoj program, bomo lahko dodali lastna odštevanja po meri! Za izboljšanje vmesnika lahko naredimo še zadnji dotik, in sicer odstranimo navidezno odštevanje, ki smo ga imeli v prejšnjih lekcijah:
|
|
Drugič, zdaj, ko imamo dejanski datum, s katerim se lahko igramo, lahko izračunamo čas do omenjenega datuma:
|
|
In tretjič, povečamo velikost okna, da bomo imeli več prostora za naše nove kartice:
|
|
Veliko lepše.
Naša aplikacija do sedaj
Main.qml:
|
|