Aggiungere una finestra
Rendere utili i programmi
Abbiamo una finestra, abbiamo le schede e abbiamo le azioni. Dobbiamo ancora trovare un modo per inserire un nome, una descrizione e una data a nostra scelta.
Un modo potrebbe essere quello di creare una nuova pagina dove mettere gli elementi gli elementi per l'inserimento. Tuttavia utilizzare una pagina intera solo per inserire un nome, una descrizione e una data sembra un po' eccessivo.
Utilizzeremo invece una finestra di dialogo.

Apertura della finestra
pageStack.initialPage: Kirigami.ScrollablePage {
// ...
actions: [
Kirigami.Action {
id: addAction
icon.name: "list-add"
text: i18nc("@action:button", "Add kountdown")
onTriggered: addDialog.open()
}
]
}Per prima cosa modifichiamo l'azione del tutorial precedente: solo un Kirigami.Action che attiva la funzione open() della finestra di dialogo.
Finestre di dialogo per l'aggiunta del conto alla rovescia
Il nuovo componente che aggiungiamo è un Kirigami.Dialog. Le finestre di dialogo vengono visualizzate al centro della finestra e possono essere utilizzate per fornire informazioni aggiuntive rilevanti per il contenuto corrente. Non possono essere spostati, ma adattano la propria dimensione alla finestra.
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
// I layout dei moduli aiutano ad allineare e strutturare un layout con diversi input
Kirigami.FormLayout {
// I campi di testo ti consentono di inserire testo in una casella di testo sottile
Controls.TextField {
id: nameField
// Fornisce un'etichetta allegata al campo di testo
Kirigami.FormData.label: i18nc("@label:textbox", "Name*:")
// Cosa fare dopo che l'input è stato accettato (cioè premuto Invio) In questo caso,
// sposta lo stato attivo sul campo successivo
onAccepted: descriptionField.forceActiveFocus()
}
Controls.TextField {
id: descriptionField
Kirigami.FormData.label: i18nc("@label:textbox", "Description:")
placeholderText: i18n("Optional")
// Ancora una volta, sposta lo stato attivo sul campo successivo
onAccepted: dateField.forceActiveFocus()
}
Controls.TextField {
id: dateField
Kirigami.FormData.label: i18nc("@label:textbox", "ISO Date*:")
// D significa un numero richiesto compreso tra 1 e 9, 9 significa un numero
// richiesto compreso tra 0 e 9
inputMask: "D999-99-99"
// Qui confermiamo l'operazione proprio come fare clic sul pulsante OK
onAccepted: addDialog.onAccepted()
}
Controls.Label {
text: "* = required fields"
}
}
// La logica del dialogo va qui
}
// ...
}Le finestre di dialogo per impostazione predefinita hanno un header e un footer, entrambi ereditati da Controls.Dialog.
L'intestazione per impostazione predefinita include un titolo e un pulsante di chiusura che può essere disabilitato con showCloseButton. Il piè di pagina per impostazione predefinita include un pulsante di chiusura e può essere sovrascritto con standardButtons.
Per prima cosa lo impostiamo per mostrare un pulsante "Ok" e un pulsante "Annulla", aggiungiamo un po' di riempimento e aggiungiamo una preferredWidth ragionevole. La larghezza preferita è la dimensione prevista predefinita della finestra di dialogo, che può aumentare se necessario. Possiamo usare lo standard Kirigami.Units che rivisiteremo più avanti.
Poi arriviamo a un Kirigami.FormLayout. A differenza di un ColumnLayout, il layout dei suoi componenti figlio è automatico e centrato, con etichette opzionali. Come suggerisce il nome, viene utilizzato per creare moduli di input.
Questi layout di modulo sono progettati per funzionare con una varietà di tipi di input diversi, anche se ci limitiamo ai semplici input Controls.Textfield che ci forniscono semplici caselle di testo in cui scrivere cose.
Abbiamo creato elementi Textfield che agiscono come:
- Ingresso per il nome del nostro conto alla rovescia
- Ingresso per la descrizione del nostro conto alla rovescia
- Ingresso per le date che stiamo aspettando, che devono essere fornite nel formato
YYYY-MM-DD
All'interno di ciascuno di questi elementi Controls.Textfield, stiamo impostando una proprietà Kirigami.FormData.label che ci consente di definire le etichette per essi. Il modulo presenterà le etichette corrette a sinistra di ciascuno di questi campi di immissione testo.
Infine, stiamo anche impostando la proprietà onAccepted per attivare il metodo forceActiveFocus() del campo seguente; questo cambierà il campo attivo una volta che l'utente preme il tasto INVIO, migliorando l'usabilità del modulo.
Abbiamo anche impostato una proprietà chiamata inputMask sul campo di testo per la nostra data. Impostandolo su "D999-99-99" impedisce agli utenti di inserire qualcosa che potrebbe interrompere la funzionalità dell'applicazione (come il testo), limitandoli a inserire solo cifre che possiamo quindi provare ad analizzare in un oggetto data.
Una volta completata l'interfaccia utente per la finestra di dialogo, dobbiamo modificare il modo in cui si comporta. Per questo abbiamo bisogno di tre cose:
- Mostra il pulsante Ok solo quando i campi obbligatori sono compilati
- Aggiungere le informazioni di input al modello
- Cancella il modulo di input
Kirigami.Dialog {
// ... Una volta inizializzato Kirigami.Dialog, vogliamo creare un'associazione personalizzata
// per rendere visibile il pulsante Ok solo se i campi di testo richiesti sono compilati. Per
// questo usiamo Kirigami.Dialog.standardButton(pulsante):
Component.onCompleted: {
const button = standardButton(Kirigami.Dialog.Ok);
// () => è una funzione freccia JavaScript
button.enabled = Qt.binding( () => requiredFieldsFilled() );
}
onAccepted: {
// L'associazione viene creata, ma dobbiamo ancora renderla non cliccabile a meno che i
// campi non siano compilati
if (!addDialog.requiredFieldsFilled()) return;
appendDataToModel();
clearFieldsAndClose();
}
}La prima cosa da fare è creare un legame tra la proprietà enabled del pulsante OK e un controllo se i campi sono compilati, che in questo caso deve essere fatto con Qt.binding() in JavaScript. In effetti la riga:
button.enabled = Qt.binding( () => requiredFieldsFilled() );è simile ai collegamenti QML che abbiamo visto finora, come nel seguente pseudo-codice:
enabled: requiredFieldsFilled()Il gestore del segnale che attiva il pulsante Ok è onAccepted. Rimane vuoto e senza fare nulla se i campi obbligatori sono compilati; in caso contrario, aggiungerà l'input al modello e cancellerà la finestra di dialogo per la prossima volta che verrà aperta.
Kirigami.Dialog {
// ... Controlliamo che il nameField non sia vuoto e che il dateField (che ha una inputMask) sia
// completamente riempito
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();
}
}Per il campo del nome richiesto, tutto ciò che dobbiamo fare è verificare se il testo del campo è una stringa vuota. Per il campo della data, poiché ha una maschera di input, dobbiamo invece utilizzare acceptableInput, che diventa vero solo quando l'intero campo è riempito e contiene solo caratteri accettabili.
Quindi, il metodo append() del nostro modello di elenco kountdownModel aggiunge un oggetto JavaScript che include le proprietà che abbiamo fornito.
Infine, ci assicuriamo di cancellare i campi di testo impostando le loro proprietà text su una stringa vuota, quindi close().
Una volta salvati i nostri file e creato il nostro programma, saremo in grado di aggiungere i nostri conti alla rovescia personalizzati! Possiamo fare un ultimo tocco per migliorare l'interfaccia, ovvero rimuovere il conto alla rovescia fittizio che avevamo nelle lezioni precedenti:
| |
In secondo luogo, ora che abbiamo una data effettiva con cui giocare, possiamo calcolare il tempo fino a tale data:
| |
E in terzo luogo aumenta la dimensione della finestra in modo da avere più spazio per le nostre nuove carte:
| |
Molto più bello.
Il nostro programma finora
Main.qml:
| |
