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()
}
]
}
First we edit the action from the previous tutorial: just a Kirigami.Action that triggers the dialog's open() function.
Dialogen die aftellen toevoegen
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
// 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.
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.
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
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.
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:
|
|