Rozloženia, ListView a karty
Rozloženie vášho obsahu
Teraz, keď rozumieme, ako fungujú stránky, je čas pridať na ne obsah. Prejdeme niekoľkými dôležitými komponentmi rozloženia a prvkami, ktoré budú užitočné pri navrhovaní našej aplikácie.
Na konci tejto sekcie budete mať pekne vyzerajúcu aplikáciu.
ListViews
Ak ste niekedy použili Discover, NeoChat alebo Systémové nastavenia Plasma, stretli ste sa s ListView. Jednoducho povedané, umožňuje vám zobrazovať dáta v zozname.
pageStack.initialPage: Kirigami.ScrollablePage {
// ...
Kirigami.CardsListView {
id: cardsView
model: kountdownModel
delegate: kountdownDelegate
}
}To vyzerá záhadne, ale nebojte sa. Začnime od začiatku.
Tento komponent pridávame do našej Kirigami.ScrollablePage z posledného tutoriálu.
Používame Kirigami.CardsListView, čo je ListView, ktorý nám umožňuje jednoducho zobrazovať karty v zozname. Avšak ListViews sú vytvorené na zobrazovanie dát prevzatých z modelu — na automatické naplnenie sa zo sady dát, na ktorú ich nasmerujeme. Tu prichádza vlastnosť model: v tomto príklade ukazuje na kountdownModel.
Model
Kirigami.ApplicationWindow {
// ...
ListModel {
id: kountdownModel
// Každý ListElement je prvok v zozname obsahujúci informácie
ListElement {
name: "Dog birthday!!"
description: "Big doggo birthday blowout."
date: 100
}
}
// ...
}Pridávame náš kountdownModel do Kirigami.ApplicationWindow z posledného tutoriálu.
Model definuje spôsob, akým je dátový záznam štruktúrovaný. Náš kountdownModel sa zatiaľ bude skladať iba z jedného prvku. Pozrením na náš ListElement vyššie vidíme, ako sú štruktúrované dáta nášho kountdownModel: obsahuje meno, popis a dátum. Toto nie je nemenné a vo vašom modeli môžete mať rôzne druhy dát. Prvé dve sú len reťazce a tretí je číslo, ktoré používame ako zástupný symbol.
Poznámka
Keďže QML je postavené na JavaScripte, mnohé funkcie tohto jazyka sú dostupné na použitie v súboroch QML. Avšak premenné QML musia byť prefixovanéproperty, pokiaľ to nie je vnútri bloku kódu JS. Viac o tom si môžete prečítať na tejto stránke.Modely sú tiež užitočné v tom, ako sa dajú modifikovať použitím niekoľkých metód. Niektoré dôležité sú:
- ListModel.append(yourobject: jsobject) pridá objekt JavaScript (JSObject)
yourobjectdo ListModel a umiestni ho za poslednú položku v modeli. Aby to fungovalo správne, musíte poskytnúť JSObject so správnymi vlastnosťami a zodpovedajúcimi dátovými typmi. - ListModel.get(index: int) vráti JSObject na pozícii indexu, ktorý poskytnete.
- ListModel.remove(index: int, count: int) odstráni JSObject na poskytnutej pozícii
indexa toľko po nej, koľko uvediete vcount(1 zahŕňa iba JSObject na poskytnutej pozícii indexu) - ListModel.set(index: int, yourobject: jsobject) zmení položku na poskytnutej pozícii
indexhodnotami poskytnutými vyourobject. Rovnaké pravidlá ako priappend().
Delegát
Zatiaľ čo náš kountdownModel obsahuje dáta, ktoré sa zobrazia, náš kountdownDelegate spracuje, ako sa dáta zobrazia v ListView. Na to používame Kirigami.CardsListView navrhnutý na zobrazovanie delegátov typu kariet a tieto delegáty budú vizuálne reprezentované prostredníctvom Kirigami.AbstractCard.
Delegáty automaticky prijímajú vlastnosti inštancií ListElement, ktoré sme špecifikovali v našom modeli. Preto sa môžeme jednoducho odvolávať na ich vlastnosti name, description a date, ako keby to boli bežné premenné v našom delegáte.
Zostavenie delegátovej karty
Komponent Component, ktorý bude reprezentovať náš delegát, sa dá pridať do nášho Kirigami.ApplicationWindow. Potom skontrolujeme, čo robí každá časť nášho komponentu delegáta.
Kirigami.ApplicationWindow {
// ...
Component {
id: kountdownDelegate
Kirigami.AbstractCard {
contentItem: Item {
// implicitWidth/Height definujú prirodzenú šírku/výšku položky, ak nie je
// špecifikovaná žiadna šírka alebo výška. Nastavenie nižšie definuje preferovanú
// veľkosť komponentu na základe jeho obsahu
implicitWidth: delegateLayout.implicitWidth
implicitHeight: delegateLayout.implicitHeight
GridLayout {
id: delegateLayout
anchors {
left: parent.left
top: parent.top
right: parent.right
}
rowSpacing: Kirigami.Units.largeSpacing
columnSpacing: Kirigami.Units.largeSpacing
columns: root.wideScreen ? 4 : 2
Kirigami.Heading {
level: 1
text: date
}
ColumnLayout {
Kirigami.Heading {
Layout.fillWidth: true
level: 2
text: name
}
Kirigami.Separator {
Layout.fillWidth: true
visible: description.length > 0
}
Controls.Label {
Layout.fillWidth: true
wrapMode: Text.WordWrap
text: description
visible: description.length > 0
}
}
Controls.Button {
Layout.alignment: Qt.AlignRight
Layout.columnSpan: 2
text: i18n("Edit")
// onClicked: bude hotové... čoskoro!
}
}
}
}
}
// ...
}implicitWidth a implicitHeight
Prvou časťou, na ktorú sa pozrieme, je spravovanie šírky a výšky nášho komponentu:
Kirigami.AbstractCard {
contentItem: Item {
implicitWidth: delegateLayout.implicitWidth
implicitHeight: delegateLayout.implicitHeight
GridLayout {
id: delegateLayout
// ...
}
}
}Keď sa pozrieme na náš Kirigami.AbstractCard, prvé vlastnosti, ktoré nastavujeme, sú implicitWidth a implicitHeight. Nastavili sme ich na delegateLayout.implicitWidth a delegateLayout.implicitHeight, t.j. implicitWidth a implicitHeight prvku GridLayout.
Implicitné šírky a výšky sú vlastnosti dostupné v akomkoľvek Item, ktoré fungujú ako nápovedy a sú nastavené ako predvolené alebo záložné, ak pre tieto komponenty nie je nastavená žiadna explicitná šírka alebo výška. Tieto hodnoty sú predvolene 0x0, preto je veľmi dôležité, aby ste ich definovali v surových komponentoch Item, ako je to urobené vyššie.
Tu sme nastavili implicitWidth a implicitHeight nášho Kirigami.AbstractCard na hodnoty GridLayout nižšie, aby sme zabezpečili, že sa nevyleje z karty. Takto karta zaberie toľko miesta, koľko je potrebné pre jej obsah.
Rozloženia
GridLayout je vnútri komponentu Item, ktorý sme poskytli pre vlastnosť contentItem. Toto je Item, ktorý obsahuje to, čo sa zobrazí vo vašej karte.
Musíme tiež zvoliť rozloženie pre naše komponenty, aby sa navzájom neprekladali. Existujú tri hlavné typy, z ktorých si môžeme vybrať:
- ColumnLayout rozloží vaše komponenty vertikálne, v jednom stĺpci
- RowLayout rozloží vaše komponenty horizontálne, v jednom riadku
- GridLayout rozloží vaše komponenty v mriežke so zostavou podľa vášho výberu
S ColumnLayout a RowLayout stačí napísať naše komponenty vnútri komponentu Layout. Ako vidíte, rozhodli sme sa pre GridLayout, čo obnáša trochu viac ručnej práce.
GridLayout {
id: delegateLayout
anchors {
left: parent.left
top: parent.top
right: parent.right
}
rowSpacing: Kirigami.Units.largeSpacing
columnSpacing: Kirigami.Units.largeSpacing
columns: root.wideScreen ? 4 : 2
// ...
}Prvá vec, ktorú vidíte, sú naše anchors. Systém ukotvenia QtQuick poskytuje užitočný spôsob, ako zabezpečiť, aby boli vaše komponenty umiestnené v určitých častiach rodičovského komponentu. Ukotvili sme náš GridLayout doľava, hore a doprava rodičovskej karty, čím zabezpečíme, že sa náš obsah roztiahne cez celú kartu.
Ďalej špecifikujeme medzery medzi riadkami a stĺpcami v rámci našej mriežky, aby sa naše komponenty nezhlukovaly. Kirigami poskytuje niekoľko praktických preddefinovaných jednotiek na tento účel:
| Jednotka Kirigami | Pixely |
|---|---|
| smallSpacing | 4px |
| largeSpacing | 8px |
| gridUnit | 18px |
Poznámka
KDE Visual Design Group (VDG) má omnoho viac informácií o rôznych jednotkách definovaných v Plasma a Kirigami na stránke Human Interface Guidelines.Ako si možno pamätáte, root je id nášho Kirigami.ApplicationWindow. Poskytuje vlastnosť wideScreen, používanú na určenie, či je aktuálna obrazovka zariadenia široká (t.j. monitor počítača alebo telefón na šírku). Používame tu ternárny podmienený operátor na zmenu počtu stĺpcov v našej mriežke v závislosti od obrazovky, ktorú používame: ak je široká, mriežka bude mať 4 stĺpce, inak bude mať 2.
Komponenty
Mohli by sme jednoducho vytvoriť tri popisky v rámci nášho komponentu delegáta a bolo by to, ale nevyzeralo by to obzvlášť pekne. Využijeme niekoľko ďalších pohodlných komponentov:
GridLayout {
// ...
Kirigami.Heading {
Layout.fillHeight: true
level: 1
text: date
}
ColumnLayout {
Kirigami.Heading {
Layout.fillWidth: true
level: 2
text: name
}
Kirigami.Separator {
Layout.fillWidth: true
visible: description.length > 0
}
Controls.Label {
Layout.fillWidth: true
wrapMode: Text.WordWrap
text: description
visible: description.length > 0
}
}
Controls.Button {
Layout.alignment: Qt.AlignRight
Layout.columnSpan: 2
text: i18n("Edit")
}
}
Ako vyzerá vlastná karta
- Vľavo, Kirigami.Heading: používa
datezListElementako nadpis úrovne 1. - V strede, ColumnLayout: má Kirigami.Heading, ktorý zobrazuje názov úlohy; Kirigami.Separator, ktorý poskytuje horizontálnu čiaru; a Controls.Label, ktorý zobrazuje voliteľný popis úlohy. Posledné dva komponenty majú vlastnosť visible, ktorá kontroluje, či je popis prázdny alebo nie, a zobrazuje komponenty v závislosti od výsledku
description.length > 0. - Vpravo, Controls.Button: tlačidlo, ktoré bude niečo robiť... čoskoro!
Naša aplikácia doteraz
Main.qml:
| |

Tak tu je naša základná karta!
S týmito krokmi sme položili základný základ pre pridanie všetkej funkčnosti do našej aplikácie.