Formulário delegados em suas páginas de configurações
Os Addons do Kirigami é um conjunto adicional de componentes visuais que funcionam bem em dispositivos móveis e desktops, com garantia de compatibilidade entre plataformas. Ele utiliza Kirigami internamente para criar seus componentes.
Você aprendeu como adicionar as páginas Sobre e Sobre o KDE ao seu aplicativo. Agora você poderá usar os mesmos componentes internos para criar suas páginas de configurações.
A estrutura do projeto deve ser semelhante a esta:
addonsexample
├── CMakeLists.txt
├── main.cpp
├── Main.qml
├── MyAboutPage.qml
└── SettingsPage.qml
Alterações necessárias
Altere Main.qml
para incluir nossa nova página de configurações:
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)
}
}
}
}
}
Agora podemos começar a verificar os componentes usados para criar nossa página de Configurações: o Cartão de Formulário e seus Delegados.
Formulários delegados
FormCard e FormCardPage
[FormCard.FormCard](https://api.kde.org/frameworks/kirigami-addons /html/classFormCard.html) é o componente principal que usaremos para agrupar todos os seus componentes filhos, os Delegados.
Usamos um cartão de formulário na introdução aos Addons do Kirigami anteriormente. Seu principal objetivo é servir como um contêiner para outros componentes, seguindo uma cor diferente do fundo, de forma semelhante a um Kirigami.Card.
Crie um novo arquivo SettingsPage.qml
:
import QtQuick
import org.kde.kirigamiaddons.formcard as FormCard
FormCard.FormCardPage {
FormCard.FormCard {
// É aqui que todos os nossos delegados vão!
}
FormCard.FormCard {
// É aqui que todos os nossos delegados vão!
}
}
Como estamos criando um arquivo QML separado para nossa página de Configurações e como precisamos nos preparar para uma possível rolagem em nossa página, usamos um FormCard.FormCardPage
, que herda Kirigami.ScrollablePage.
O interessante da página do cartão de formulário é que ela vem com um layout interno, portanto, nenhum ColumnLayout adicional é necessário e nossos delegados podem ser adicionados diretamente a ela.
Nota
É possível usar delegados do FormCard diretamente com um Kirigami.ScrollablePage, mas nesse caso você precisará adicionar seus próprios layouts.FormHeader
Para cada [FormCard](https://api.kde.org/frameworks/kirigami-addons /html/classFormCard.html) que você deseja criar, você pode criar um [FormHeader](https://api.kde.org/frameworks/kirigami-addons /html/classFormHeader.html) logo antes dele. O cabeçalho usa texto em negrito e aparece logo acima do cartão de formulário.
import org.kde.kirigamiaddons.formcard as FormCard
FormCard.FormCardPage {
FormCard.FormHeader {
title: i18n("General")
}
FormCard.FormCard {
// Nossos delegados vão aqui...
}
FormCard.FormHeader {
title: i18n("Accounts")
}
FormCard.FormCard {
// Nossos delegados vão aqui...
}
}
FormTextDelegate e FormSectionText
Vamos começar de forma simples, com texto simples.
FormSectionText
simplesmente adiciona um delegado fino contendo um rótulo. FormTextDelegate
tem texto e uma descrição em cinza.
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 ™️")
}
}
}
Adicionamos um texto fictício para a detecção hipotética do tema. Se quiséssemos ter uma detecção real do esquema de cores, no futuro isso poderia ser feito de forma semelhante ao Neochat (código aqui), utilizando um modelo C++ com KColorSchemeManager.
Na seção Contas Online, vemos uma propriedade adicional, leading
. Podemos adicionar um Item a ela para que apareça antes do texto. Sua propriedade oposta, trailing
, seria capaz de mostrar um Item após o texto, mas não a usaremos em nosso programa.
Usamos um Kirigami.Icon aqui para simplificar, mas isso também pode ser implementado usando um Kirigami.Avatar que obtém as informações de um modelo, como é feito no Neochat aqui.
Deve ficar assim:

FormButtonDelegate
O [FormButtonDelegate](https://api.kde.org/frameworks/kirigami-addons /html/classFormButtonDelegate.html) é visualmente semelhante a um FormTextDelegate, mas é clicável e exibe uma seta apontando para a direita. Já o usamos na introdução aos Addons do Kirigami anteriormente.
Enquanto o FormTextDelegate tinha as propriedades leading
e trailing
para mostrar um item antes e depois do conteúdo principal, o FormButtonDelegate possui apenas a propriedade leading
, porque o lado direito é ocupado pela seta.
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!")
}
}
}
Usamos a propriedade icon.name
para definir um ícone de mais (+) que aparecerá após o espaço onde o leading
apareceria e antes do conteúdo principal. Este é um padrão comum para indicar que seu botão adicionará algo a uma lista.
Como este exemplo é apenas para fins ilustrativos, não nos aprofundamos no que seria feito quando o botão fosse clicado: ele apenas imprime "Clicado!" no terminal. Poderíamos criar uma nova página para criação de conta que adicionasse outro usuário a um modelo e, em seguida, colocasse a página na visualização, semelhantemente ao que fizemos em Main.qml
.

FormRadioDelegate, FormCheckDelegate e FormSwitchDelegate
O RadioButton, o CheckBox e o Switch são componentes muito utilizados em qualquer interface de usuário. Os Addons do Kirigami os fornece como [FormRadioDelegate](https://api.kde.org/frameworks/kirigami-addons /html/classFormRadioDelegate.html), [FormCheckDelegate](https://api.kde.org/frameworks/kirigami-addons /html/classFormCheckDelegate.html) e [FormSwitchDelegate](https://api.kde.org/frameworks/kirigami-addons /html/classFormSwitchDelegate.html).
Suas únicas propriedades principais são text
e description
. Elas são diferentes no uso porque todas herdam AbstractButton, e portanto, espera-se que você use seus sinais e manipuladores: checked e onChecked, toggled e onToggled, clicked e onClicked.
Queremos criar uma funcionalidade de salvamento automático em nosso aplicativo e queremos mostrar suas configurações apenas se o usuário tiver habilitado essa funcionalidade. Crie uma nova seção usando um [FormCard](https://api.kde.org/frameworks/kirigami-addons /html/classFormCard.html) e um [FormHeader](https://api.kde.org/frameworks/kirigami-addons /html/classFormHeader.html), depois adicione um [FormSwitchDelegate](https://api.kde.org/frameworks/kirigami-addons /html/classFormSwitchDelegate.html) e um [FormRadioDelegate](https://api.kde.org/frameworks/kirigami-addons /html/classFormRadioDelegate.html).
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
}
}
Nós vinculamos a visibilidade de cada botão de opção a um botão de opção, para que eles só apareçam quando o botão estiver habilitado.
Melhores práticas
Clique aqui para ler mais
Se você tem alguma experiência em programação em linguagens imperativas como C++, você pode ficar tentado a definir a propriedade checked
do switch para alterar a visibilidade dos botões de opção para true
com uma atribuição JavaScript como:
checked: {
radio1.visible = true;
radio2.visible = true;
radio3.visible = true;
}
Isso não é muito eficiente para a linguagem declarativa do QML e seus sinais e slots. Tente usar vinculações QML, como no caso de visible: autosave.checked
, o máximo possível, em vez de expressões JavaScript.
Veja esta página para detalhes.

Para testar nossa caixa de seleção, podemos adicionar um novo [FormCheckDelegate](https://api.kde.org/frameworks/kirigami-addons /html/classFormCheckDelegate.html) à nossa seção Geral.
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!")
}
}
}
}
Aqui, usamos o manipulador de sinais onToggled
para exibir um texto fictício que simula um ícone de bandeja aparecendo no sistema. Se você realmente quisesse, poderia facilmente implementar um ícone de bandeja usando SystemTrayIcon.
Até agora, nossa aplicação deve ficar assim:

FormComboBoxDelegate
O componente ComboBox comum pode ser criado usando um [FormComboBoxDelegate](https://api.kde.org/frameworks/kirigami-addons /html/classFormComboBoxDelegate.html).
Este combobox tem várias propriedades úteis que podemos utilizar: editable
, displayText
e displayMode
.
Definir editable: true
permite que o usuário edite o texto do combobox, o que é útil caso seja necessário adicionar novas opções ao combobox:

Sempre que precisar mostrar texto adicional antes de cada opção, você pode usar algo como displayText: "Perfil: " + currentText
:

E o mais interessante, que usaremos em nosso exemplo, é o displayMode
. Ele pode ter três opções:
- FormComboBoxDelegate.ComboBox: a pequena caixa padrão mostrando uma lista de opções.

- FormComboBoxDelegate.Dialog: uma caixa de diálogo que mostra uma lista de opções no meio da janela, como uma Kirigami.OverlaySheet.

- FormComboBoxDelegate.Page: uma nova página contendo uma lista de opções exibidas em uma janela separada.

Adicione o seguinte entre os delegados "Esquema de cores atual" e "Mostrar ícone da bandeja" no seu cartão de formulário "Geral".
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"]
}
Com a caixa de seleção, nossa página Configurações deve ficar assim:

FormDelegateSeparator
Nossa página de Configurações está tomando forma, mas cada seção está começando a ficar longa. Podemos adicionar alguns FormDelegateSeparators para deixar nossa página mais organizada:
import QtQuick 2.15
import org.kde.kirigami 2.20 as Kirigami
import org.kde.kirigamiaddons.formcard 1.0 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!")
}
}
}
Geralmente, você pode usar separadores sempre que notar grandes distinções entre componentes, embora a escolha de onde colocá-los seja, em última análise, sua. Por exemplo, na seção Geral, a caixa de seleção difere de seus componentes anteriores, pois não começa com texto; na seção Salvamento automático, o separador agrupa os botões de opção; e na seção Contas, adicionar um separador entre a última conta e o botão fornece algum foco adicional ao botão.
As propriedades above
e below
são bastante autoexplicativas quando se trata de seu uso: você passa o id
dos componentes acima e abaixo do separador. Quando elas são definidas, o separador desaparece rapidamente sempre que o item acima ou abaixo é destacado/passado pelo mouse. Elas são mais úteis, por exemplo, quando você precisa gerar componentes dinamicamente e não pode presumir automaticamente qual item virá imediatamente antes ou depois do separador. Esse seria o caso na seção Contas da nossa aplicação uma vez que a lógica para adicionar novas contas fosse implementada, nesse caso sempre poderíamos pegar o último item do modelo para fazer isso.

Observe como o separador acima da configuração do ícone da bandeja não aparece enquanto o mouse passa por ele.