Forma i delegati nelle pagine delle impostazioni
Kirigami Addons è un insieme aggiuntivo di componenti visivi che funzionano bene su dispositivi mobili e desktop e sono garantiti multipiattaforma. Utilizza Kirigami sotto il cofano per creare i suoi componenti.
Hai imparato come aggiungere Pagine Informazioni e Informazioni su KDE alla tua applicazione. Ora sarai in grado di utilizzare gli stessi componenti interni per creare le tue pagine di impostazioni.
La struttura del progetto dovrebbe assomigliare a questa:
addonsexample
├── CMakeLists.txt
├── main.cpp
├── Main.qml
├── MyAboutPage.qml
└── SettingsPage.qmlModifiche necessarie
Modifica Main.qml per includere la nostra nuova pagina Impostazioni:
import QtQuick
import QtQuick.Layouts
import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.formcard as FormCard
import org.kde.about 1.0
Kirigami.ApplicationWindow {
id: root
width: 600
height: 700
Component {
id: aboutkde
FormCard.AboutKDE {}
}
Component {
id: aboutpage
MyAboutPage {}
}
Component {
id: settingspage
SettingsPage {}
}
pageStack.initialPage: Kirigami.ScrollablePage {
ColumnLayout {
FormCard.FormCard {
FormCard.FormButtonDelegate {
id: aboutKDEButton
icon.name: "kde"
text: i18n("About KDE Page")
onClicked: root.pageStack.layers.push(aboutkde)
}
FormCard.FormButtonDelegate {
id: aboutPageButton
icon.name: "applications-utilities"
text: i18n("About Addons Example")
onClicked: root.pageStack.layers.push(aboutpage)
}
FormCard.FormButtonDelegate {
id: settingsButton
icon.name: "settings-configure"
text: i18n("Single Settings Page")
onClicked: root.pageStack.layers.push(settingspage)
}
}
}
}
}Ora possiamo iniziare a verificare i componenti utilizzati per creare la nostra pagina Impostazioni: la scheda modulo e i suoi delegati.
Delegati modulo
FormCard e FormCardPage
FormCard.FormCard è il componente principale che useremo per raggruppare tutti i suoi componenti figli, i Delegati.
In precedenza abbiamo utilizzato una scheda modulo nell'Introduzione ai componenti aggiuntivi di Kirigami. Il suo scopo principale è quello di fungere da contenitore per altri componenti seguendo un colore diverso dallo sfondo, in modo simile a una Kirigami.Card.
Crea un nuovo file "SettingsPage.qml":
import QtQuick
import org.kde.kirigamiaddons.formcard as FormCard
FormCard.FormCardPage {
FormCard.FormCard {
// È qui che vanno tutti i nostri delegati!
}
FormCard.FormCard {
// È qui che vanno tutti i nostri delegati!
}
}Poiché stiamo creando un file QML separato per la nostra pagina Impostazioni e poiché dobbiamo prepararci per un potenziale scorrimento nella nostra pagina, utilizziamo una FormCard.FormCardPage, che eredita Kirigami.ScrollablePage.
L'aspetto interessante della pagina della scheda modulo è che viene fornita con un layout interno, quindi non è necessario alcun ColumnLayout aggiuntivo e i nostri delegati possono essere aggiunti direttamente ad essa.
Note
È possibile utilizzare i delegati FormCard direttamente con un Kirigami.ScrollablePage, ma in tal caso dovrai aggiungere i tuoi layout.FormHeader
Per ogni FormCard che vuoi creare, puoi creare un FormHeader subito prima. L'intestazione utilizza testo in grassetto e viene visualizzata proprio sopra la scheda del modulo.
import org.kde.kirigamiaddons.formcard as FormCard
FormCard.FormCardPage {
FormCard.FormHeader {
title: i18n("General")
}
FormCard.FormCard {
// I nostri delegati vanno qui...
}
FormCard.FormHeader {
title: i18n("Accounts")
}
FormCard.FormCard {
// I nostri delegati vanno qui...
}
}FormTextDelegate e FormSectionText
Iniziamo in modo semplice, con testo semplice.
FormSectionText aggiunge semplicemente un thin delegato contenente un'etichetta. FormTextDelegate contiene testo e una descrizione in grigio.
import QtQuick
import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.formcard as FormCard
FormCard.FormCardPage {
FormCard.FormHeader {
title: i18n("General")
}
FormCard.FormCard {
FormCard.FormTextDelegate {
text: i18n("Current Color Scheme")
description: "Breeze"
}
}
FormCard.FormHeader {
title: i18n("Accounts")
}
FormCard.FormCard {
FormCard.FormSectionText {
text: i18n("Online Account Settings")
}
FormCard.FormTextDelegate {
leading: Kirigami.Icon {source: "user"}
text: "John Doe"
description: i18n("The Maintainer ™️")
}
}
}Aggiungiamo del testo fittizio per l'ipotetico rilevamento del tema. Se volessimo avere un effettivo rilevamento dello schema di colori, in futuro potremmo farlo in modo simile a Neochat (codice qui), facendo uso di un modello C++ con KColorSchemeManager.
Nella sezione Account in linea, vediamo una proprietà aggiuntiva, leading. Possiamo aggiungere un Elemento in modo che appaia prima del testo. La sua proprietà opposta, trailing, sarebbe in grado di mostrare un oggetto dopo il testo, ma non lo useremo nel nostro programma.
Usiamo un Kirigami.Icon qui per semplicità, ma questo potrebbe anche essere implementato utilizzando un Kirigami Addons Avatar che prende le informazioni da un modello, come fatto in Neochat.
L'aspetto finale dovrebbe essere questo:

FormButtonDelegate
Il FormButtonDelegate è visivamente simile a FormTextDelegate, ma è selezionabile e mostra una freccia che punta a destra. L'abbiamo già utilizzato nell'Introduzione ai componenti aggiuntivi di Kirigami.
Mentre FormTextDelegate aveva le proprietà leading e trailing per mostrare un elemento prima e dopo il contenuto principale, il FormButtonDelegate ha solo la proprietà leading, perché il lato destro è occupato dalla freccia.
import QtQuick
import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.formcard as FormCard
FormCard.FormCardPage {
FormCard.FormHeader {
title: i18n("General")
}
FormCard.FormCard {
FormCard.FormTextDelegate {
text: i18n("Current Color Scheme")
description: "Breeze"
}
}
FormCard.FormHeader {
title: i18n("Accounts")
}
FormCard.FormCard {
FormCard.FormSectionText {
text: i18n("Online Account Settings")
}
FormCard.FormTextDelegate {
leading: Kirigami.Icon {source: "user"}
text: "John Doe"
description: i18n("The Maintainer ™️")
}
FormCard.FormButtonDelegate {
icon.name: "list-add"
text: i18n("Add a new account")
onClicked: console.info("Clicked!")
}
}
}Usiamo la sua proprietà icon.name per impostare un'icona più (+) in modo che appaia dopo lo spazio in cui apparirà leading e prima del main content. Questo è uno schema comune per indicare che il tuo pulsante aggiungerà qualcosa a un elenco.
Poiché questo esempio è per semplici scopi illustrativi, non approfondiamo cosa si farebbe una volta cliccato il pulsante: viene semplicemente stampato "Clicked!" to the terminal. Potremmo potremmo creare una nuova pagina per la creazione di un account che aggiunga un altro utente a un modello, quindi rendere visibile la pagina, in modo simile a quello che abbiamo fatto in Main.qml.

FormRadioDelegate, FormCheckDelegate e FormSwitchDelegate
RadioButton, CheckBox e Switch sono componenti molto comunemente utilizzati in qualsiasi interfaccia utente. I componenti aggiuntivi di Kirigami li forniscono come FormRadioDelegate, FormCheckDelegate e FormSwitchDelegate.
Le loro uniche proprietà principali sono "testo" e "descrizione". Sono diversi nell'utilizzo perché ereditano tutti AbstractButton e quindi ci si aspetta che tu usi i suoi segnali e gestori: check e onChecked, toggled e onToggled, clicked e onClicked.
Vogliamo creare alcune funzionalità di salvataggio automatico nella nostra applicazione e vogliamo mostrare le sue impostazioni solo se l'utente ha abilitato questa funzionalità. Crea una nuova sezione utilizzando una FormCard e una FormHeader, quindi aggiungi una FormSwitchDelegate e un FormRadioDelegate.
FormCard.FormHeader {
title: i18n("Autosave")
}
FormCard.FormCard {
FormCard.FormSwitchDelegate {
id: autosave
text: i18n("Enabled")
}
FormCard.FormRadioDelegate {
text: i18n("After every change")
visible: autosave.checked
}
FormCard.FormRadioDelegate {
text: i18n("Every 10 minutes")
visible: autosave.checked
}
FormCard.FormRadioDelegate {
text: i18n("Every 30 minutes")
visible: autosave.checked
}
}Associamo la visibilità di ciascun pulsante di opzione a un interruttore, in modo che vengano visualizzati solo quando l'interruttore è abilitato.
Migliori pratiche
Fai clic qui per leggere di più
Se hai esperienza di programmazione in linguaggi imperativi come C++, potresti essere tentato di impostare la proprietà checked della proprietà dell'interruttore per impostare la visibilità dei pulsanti di opzione su "true" con un'assegnazione JavaScript come:
checked: {
radio1.visible = true;
radio2.visible = true;
radio3.visible = true;
}Ciò non è molto efficiente per il linguaggio dichiarativo di QML e i suoi segnali e slot. Prova a utilizzare il più possibile i collegamenti QML come nel caso di visible: autosave.checked anziché le espressioni JavaScript.
Per i dettagli vedi questa pagina

Per testare la nostra casella di controllo, possiamo aggiungere un nuovo FormCheckDelegate alla nostra sezione Generale.
FormCard.FormHeader {
title: i18n("General")
}
FormCard.FormCard {
FormCard.FormTextDelegate {
text: i18n("Current Color Scheme")
description: "Breeze"
}
FormCard.FormCheckDelegate {
text: i18n("Show Tray Icon")
onToggled: {
if (checkState) {
console.info("A tray icon appears on your system!")
} else {
console.info("The tray icon disappears!")
}
}
}
}Qui utilizziamo il gestore del segnale chiamato onToggled per mostrare del testo fittizio per simulare un'icona nella barra delle applicazioni che appare nel sistema. Se lo desideri davvero, puoi facilmente implementare un'icona nel vassoio utilizzando KStatusNotifierItem di KDE o SystemTrayIcon.
Alla fine la nostra applicazione dovrebbe assomigliare a questa:

FormComboBoxDelegate
Il componente ComboBox comune può essere creato utilizzando un FormComboBoxDelegate.
Questa casella combinata ha diverse proprietà utili che possiamo utilizzare: editable, displayText e displayMode.
L'impostazione "editable: true" consente all'utente di modificare il testo della casella combinata, il che è utile nel caso in cui sia necessaria l'aggiunta di nuove opzioni della casella combinata:

Ogni volta che devi mostrare del testo aggiuntivo prima di ciascuna opzione, puoi usare qualcosa come displayText: "Profile: " + currentText:

E quello più interessante, che useremo nel nostro esempio, è displayMode. Può avere tre opzioni:
- FormComboBoxDelegate.ComboBox: il piccolo riquadro standard che mostra un elenco di opzioni.

- FormComboBoxDelegate.Dialog: una finestra di dialogo che mostra un elenco di opzioni al centro della finestra, come un Kirigami.OverlaySheet.

- FormComboBoxDelegate.Page: una nuova pagina contenente un elenco di opzioni mostrate in una finestra separata.

Aggiungi quanto segue tra i delegati "Schema colori corrente" e "Mostra icona nella barra delle applicazioni" nella scheda del modulo "Generale".
FormCard.FormComboBoxDelegate {
text: i18n("Default Profile")
description: i18n("The profile to be loaded by default.")
displayMode: FormCard.FormComboBoxDelegate.ComboBox
currentIndex: 0
editable: false
model: ["Work", "Personal"]
}Con la casella di controllo, la nostra pagina Impostazioni dovrebbe assomigliare a questa:

FormDelegateSeparator
La nostra pagina Impostazioni sta prendendo forma, ma ogni sezione inizia a diventare lunga. Possiamo aggiungere alcune istanze di FormDelegateSeparator per rendere la nostra pagina più ordinata:
import QtQuick
import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.formcard as FormCard
FormCard.FormCardPage {
id: root
title: i18nc("@title", "Settings")
FormCard.FormHeader {
title: i18nc("@title:group", "General")
}
FormCard.FormCard {
FormCard.FormTextDelegate {
text: i18nc("@info", "Current Color Scheme")
description: "Breeze"
}
FormCard.FormComboBoxDelegate {
id: combobox
text: i18nc("@label:listbox", "Default Profile")
description: i18nc("@info:whatsthis", "The profile to be loaded by default.")
displayMode: FormCard.FormComboBoxDelegate.ComboBox
currentIndex: 0
editable: false
model: ["Work", "Personal"]
}
FormCard.FormDelegateSeparator {
above: combobox
below: checkbox
}
FormCard.FormCheckDelegate {
id: checkbox
text: i18nc("@option:check", "Show Tray Icon")
onToggled: {
if (checkState) {
console.info("A tray icon appears on your system!")
} else {
console.info("The tray icon disappears!")
}
}
}
}
FormCard.FormHeader {
title: i18nc("@title:group", "Autosave")
}
FormCard.FormCard {
FormCard.FormSwitchDelegate {
id: autosave
text: i18nc("@option:check", "Enabled")
}
FormCard.FormDelegateSeparator {
above: autosave
below: firstradio
visible: autosave.checked
}
FormCard.FormRadioDelegate {
id: firstradio
text: i18nc("@option:radio", "After every change")
visible: autosave.checked
}
FormCard.FormRadioDelegate {
text: i18nc("@option:radio", "Every 10 minutes")
visible: autosave.checked
}
FormCard.FormRadioDelegate {
text: i18nc("@option:radio", "Every 30 minutes")
visible: autosave.checked
}
}
FormCard.FormHeader {
title: i18nc("@title:group", "Accounts")
}
FormCard.FormCard {
FormCard.FormSectionText {
text: i18nc("@info:whatsthis", "Online Account Settings")
}
FormCard.FormTextDelegate {
id: lastaccount
leading: Kirigami.Icon {source: "user"}
text: "John Doe"
description: i18nc("@info:credit", "The Maintainer ™️")
}
FormCard.FormDelegateSeparator {
above: lastaccount
below: addaccount
}
FormCard.FormButtonDelegate {
id: addaccount
icon.name: "list-add"
text: i18nc("@action:button", "Add a new account")
onClicked: console.info("Clicked!")
}
}
}
In generale, è possibile utilizzare i separatori ogni volta che si notano distinzioni importanti tra i componenti, anche se la scelta di dove posizionarli spetta in definitiva a voi. Ad esempio, nella sezione Generale, la casella di controllo differisce dai suoi componenti precedenti poiché non inizia con il testo; nella sezione Salvataggio automatico, il separatore raggruppa i pulsanti radio; e nella sezione Account, l'aggiunta di un separatore tra l'ultimo account e il pulsante fornisce ulteriore attenzione al pulsante.
Le proprietà sopra e sotto sono piuttosto autoesplicative per quanto riguarda il loro utilizzo: si passa il "id" dei componenti sopra e sotto il separatore. Una volta impostati, il separatore scomparirà rapidamente ogni volta che l'elemento sopra o sotto viene evidenziato/passato sopra. Sono particolarmente utili, ad esempio, quando è necessario generare componenti in modo dinamico e non è possibile assumere automaticamente quale elemento verrà immediatamente prima o dopo il separatore. Questo sarebbe il caso nella sezione Account della nostra applicazione una volta implementata la logica per aggiungere nuovi account, nel qual caso potremmo sempre prendere l'ultimo elemento nel modello per farlo.

Nota come il separatore sopra l'impostazione dell'icona nella barra delle applicazioni non viene visualizzato mentre ci si passa sopra.