Een dialoog toevoegen
Uw toepassing nuttig maken
We hebben een venster, we hebben kaarten en we hebben acties. Nu moeten we nog steeds een manier vinden voor het invoeren van een naam, beschrijving en datum van uw keuze.
Een manier waarop we dit zouden kunnen doen is met het maken van een nieuwe pagina waar we de vereiste invoerelementen in plaatsen. Een gehele pagina bestemd om een naam, beschrijving en datum te leveren lijkt een beetje teveel.
In plaats daarvan zullen we een dialoog gebruiken.
Het dialoogvenster openen
pageStack.initialPage: Kirigami.ScrollablePage {
// ...
actions: [
Kirigami.Action {
id: addAction
icon.name: "list-add"
text: i18nc("@action:button", "Add kountdown")
onTriggered: addDialog.open()
}
]
}
Als eerste bewerken we de actie uit de vorige inleiding: gewoon een Kirigami.Action die de functie van de dialoog open() start.
Dialogen die aftellen toevoegen
De nieuwe component die we toevoegen is Kirigami.Dialog. Dialogen verschijnen in het centrum van het venster en kunnen gebruikt worden om extra informatie te leveren relevant voor de huidige inhoud. Ze kunnen niet verplaatst worden, maar ze passen hun eigen grootte aan aan het venster.
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
// Formulierindelingen helpen met het uitlijnen en structuren van een layout met meerdere
// invoervelden
Kirigami.FormLayout {
// Tekstvelden laten u tekst invoeren in een tekstvak
Controls.TextField {
id: nameField
// Plaatst een label bij het tekstveld
Kirigami.FormData.label: i18nc("@label:textbox", "Name*:")
// Wat te doen nadat de invoer is geaccepteerd (d.w.z. Enter is ingedrukt). In dit
// geval wordt de focus verplaatst naar het volgende veld
onAccepted: descriptionField.forceActiveFocus()
}
Controls.TextField {
id: descriptionField
Kirigami.FormData.label: i18nc("@label:textbox", "Description:")
placeholderText: i18n("Optional")
// Opnieuw wordt de focus verplaatst naar het volgende veld
onAccepted: dateField.forceActiveFocus()
}
Controls.TextField {
id: dateField
Kirigami.FormData.label: i18nc("@label:textbox", "ISO Date*:")
// D betekent een vereist cijfer tussen 1-9, 9 betekent een vereist cijfer tussen
// 0-9
inputMask: "D999-99-99"
// Hier accepteren we de wijziging door gewoon op de OK-knop te klikken
onAccepted: addDialog.onAccepted()
}
Controls.Label {
text: "* = required fields"
}
}
// De dialoog-code komt hier
}
// ...
}
Standaard hebben dialogen een Kop (header) en een Voet (footer), beide geërfd van Controls.Dialog.
Standaard heeft de kop een titel en een sluitknop die uitgeschakeld kan worden met showCloseButton. Standaard heeft de voet een sluitknop, dit is aanpasbaar met standardButtons.
We stellen het eerst zodanig in dat het een "Ok"-knop en een knop "Annuleren" toont, vervolgens voegen we nog wat opvulruimte toe, en voegen een redelijke preferredWidth toe. De voorkeur breedte is de verwachte standaard afmeting van het dialoogvenster, die indien nodig nog groter kan worden. We kunnen de standaard Kirigami.Units gebruiken die we later opnieuw zullen bezoeken.
En dan komen we bij een Kirigami.FormLayout. In tegenstelling tot een ColumnLayout, is de indeling van zijn kinderen automatisch en gecentreerd, met optioneel labels. Zoals de naam al aangeeft, wordt het gebruikt om invul-formulieren te creëren.
Deze formulierindelingen zijn ontworpen om te werken met een variëteit van verschillende invoertypen, maar nu blijven we bij eenvoudige Controls.Textfield invoer die ons eenvoudige tekstvelden geeft om dingen in te schrijven.
We hebben Textfield-elementen gemaakt die acteren als:
- Invoer voor de naam van onze aftelling
- Invoer voor de beschrijving van onze aftelling
- Invoer voor de datum waar we naar aftellen, die geleverd moet worden in een formaat
JJJJ-MM-DD
In elk van deze Controls.Textfield-elementen, voegen we een Kirigami.FormData.label-eigenschap toe waarmee we labels voor elk daarvan kunnen definiëren. Het formulier zal dan voor elk de correcte label links van de tekstvelden tonen.
En tenslotte voegen we de onAccepted-eigenschap toe om het startsignaal te geven voor forceActiveFocus()-methode voor het volgende veld; dit zal het veld dat actief is omschakelen naar het volgende veld nadat de gebruiker de ENTER-toets heeft ingedrukt, wat de bruikbaarheid van het formulier verbetert.
We hebben ook een eigenschap genaamd inputMask ingesteld op het tekstveld voor onze datum. Dit instellen op D999-99-99"
voorkomt dat gebruikers iets invoeren dat de functionaliteit van de toepassing laat breken (zoals tekst), die hen beperkt tot het alleen invoeren van cijfers die we daarna kunnen proberen te ontleden in een datum object.
Nadat de gebruikersinterface voor het dialoogvenster klaar is, moeten we het het gedrag ervan wijzigen. Daarvoor hebben we drie dingen nodig:
- De OK-knop is alleen zichtbaar als de vereiste velden ingevuld zijn
- Voeg de invoerinformatie toe aan het model
- Formulier wissen
Kirigami.Dialog {
// ... Nadat het Kirigami.Dialog is geïnitialiseerd, willen we een aangepaste binding creëren om
// ervoor te zorgen dat de Ok-knop pas zichtbaar word als de vereiste tekstvelden zijn ingevuld.
// Hiervoor gebruiken we Kirigami.Dialog.standardButton(button):
Component.onCompleted: {
const button = standardButton(Kirigami.Dialog.Ok);
// () => is een JavaScript pijl-functie
button.enabled = Qt.binding( () => requiredFieldsFilled() );
}
onAccepted: {
// De binding is gecreëerd, maar we moeten het niet klikbaar maken tenzij de velden ingevuld
// zijn
if (!addDialog.requiredFieldsFilled()) return;
appendDataToModel();
clearFieldsAndClose();
}
}
Wat als eerste gedaan moet worden is de creatie van een binding tussen de eigenschap enabled van de OK-knop en een controle of de velden zijn ingevuld, wat in dit geval gedaan moet worden met Qt.binding() in JavaScript. In feite, is de regel:
button.enabled = Qt.binding( () => requiredFieldsFilled() );
vergelijkbaar met de QML bindings die we tot nog toe hebben gezien, zoals in de volgende voorbeeld-code:
enabled: requiredFieldsFilled()
De signal handler dat de Ok-knop vrijgeeft is onAccepted. Het blijft leeg en zonder dat het iets doet als de vereiste velden zijn gevuld; als dat niet het geval is dan voert het de invoer naar het model en maakt het dialoogvenster leeg voor de volgende keer dat het wordt geopend.
Kirigami.Dialog {
// ... We controleren dat de nameField niet leeg is en dat de dateField (wat een inputMask
// heeft) compleet is ingevuld
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();
}
}
Voor ons vereiste nameField, is alles wat we moeten doen is controleren of de veldtekst een lege tekst is. Voor het dateField, omdat het een inputMask heeft, moeten we in plaats daarvan acceptableInput gebruiken, wat alleen 1 wordt als het hele veld is ingevuld is en alleen acceptable karakters bevat.
Daarna, de methode append() van ons lijstmodel kountdownModel
voegt een JavaScript object toe inclusief de eigenschappen die we hebben geleverd.
Tenslotte verzekeren we ons ervan om de tekstvelden te wissen door hun teksteigenschappen op een lege tekenreeks in te stellen, daarna close() sluit het.
Nadat we onze bestanden hebben opgeslagen en ons programma hebben gebouwd, kunnen we onze eigen aftelling toevoegen! We kunnen een laatste wijziging aanbrengen om de interface te verbeteren, namelijk de dummy aftelling verwijderen die we in de vorige lessen hadden:
|
|
Ten tweede nu we een actuele datum hebben om mee te spelen, kunnen we de tijd tot de vermelde datum berekenen:
|
|
En ten derde verhoog de venstergrootte zodat we meer ruimte hebben voor onze nieuwe kaarten:
|
|
Veel beter
Onze toepassing (app) tot zover
Main.qml:
|
|