Indelingen, Lijstweergaven en Kaarten
Uw inhoud indelen
Nu we begrijpen hoe pagina's werken, is het tijd om zaken aan de onzen toe te voegen. We zullen door een aantal belangrijke indelingscomponenten en elementen lopen die nuttig zullen zijn bij het ontwerpen van onze toepassing.
Wees niet bang voor de grote stukken code! We zullen alles bespreken wat we eerder niet hebben gedekt en aan het eind van deze sectie zult u een netjes uitziende toepassing hebben.
Lijstweergaven
Als u ooit Discover, NeoChat of Systeeminstellingen van Plasma hebt gebruikt, bent u langs een ListView gekomen. Heel eenvoudig, het laat u gegevens in een lijst tonen.
Kirigami.CardsListView {
id: cardsView
model: kountdownModel
delegate: kountdownDelegate
}
Dat lijkt cryptisch, maar geen getob. Laten we vanaf het begin beginnen.
We voegen deze component toe in onze Kirigami.ScrollablePage uit de laatste inleiding.
We gaan
Kirigami.CardsListView
gebruiken, die een ListView is en ons gemakkelijk kaarten biedt om in een lijst te tonen. Lijstweergaven zijn echter gemaakt om gegevens genomen uit een model te tonen - om automatisch zichzelf te bevolken uit een set gegevens waar we naar wijzen. Dat is waar de eigenschap model
in beeld komt: in dit voorbeeld wijst het naar kountdownModel
.
Model
ListModel {
id: kountdownModel
// Elk ListElement is een element in de lijst, die informatie bevat
ListElement {
name: "Dog birthday!!"
description: "Big doggo birthday blowout."
date: 100
}
}
We voegen onze kountdownModel
toe in onze
Kirigami.ApplicationWindow
uit de laatste inleiding.
Een model definieert de manier waarop invoer van gegevens zijn gestructureerd. Ons kountdownModel
zal, voor nu, bestaan uit slechts één element. Door naar ons bovenstaande ListElement te kijken kunnen we zien hoe gegevens van het kountdownModel
zijn gestructureerd: ze bevatten een naam, een beschrijving en een datum. Dit is niet in beton gegoten en u kunt verschillende soorten gegevens in uw model hebben. De eerste twee zijn gewoon tekenreeksen en de derde is een getal dat we als plaatshouder gebruiken.
Notitie
Omdat QML is bovenop JavaScript is gebouwd, zijn vele van deze taalfuncties beschikbaar voor gebruik in QML-bestanden. QML-variabelen moeten echter een prefix metproperty
hebben, tenzij het binnen een JS codeblok is. U kunt hier meer over lezen op deze pagina.Modellen zijn ook nuttig in hoe ze gewijzigd kunnen worden met gebruik van verschillende methoden. Enige belangrijken zijn:
- ListModel.append(yourobject: jsobject) voegt een JavaScript-object toe
yourobject
aan het ListModel en plaatst het na het laatste item in het model. Om dit juist te laten gebeuren moet u een JavaScript Object leveren met de juiste eigenschappen en overeenkomstige gegevenstypen. - ListModel.get(index: int)](https://doc.qt.io/qt-6/qml-qtqml-models-listmodel.html#get-method) geeft het JSObject terug op de indexlocatie die u levert.
- ListModel.remove(index: int, count: int) verwijdert het JSObject op de geleverde locatie van
index
en zoveel na die indexlocatie als u stopt incount
(1 stopt alleen het JSObject in de geleverde index) - ListModel.set(index: int, yourobject: jsobject) wijzigt het item op de geleverde locatie
index
met de waarden geleverd inyourobject
. Zelfde regels als metappend()
.
Overdragen
Terwijl ons kountdownModel
de gegevens bevat die getoond zullen worden, zal onze kountdownDelegate
behandelen hoe de gegevens getond zullen worden in de ListView.
Kirigami.CardsListView
is ontworpen om card-type gedelegeerden te tonen en we hebben inderdaad een element
Kirigami.AbstractCard
als onze gedelegeerde in het bovenstaande uittreksel.
Gedelegeerden ontvangen automatisch de eigenschappen van het ListElements dat we gespecificeerd hebben in ons model. We kunnen daarom gewoon refereren naar de eigenschappen name
, description
en date
van onze ListElements alsof ze een conventionele variabele zijn binnen onze gedelegeerde.
Onze delegatiekaart bouwen
De Component die onze gedelegeerde representeert kan toegevoegd worden in ons Kirigami.ApplicationWindow . We zullen daarna verder gaan door te controleren wat elk deel van onze gedelegeerde component doet.
Component {
id: kountdownDelegate
Kirigami.AbstractCard {
contentItem: Item {
// implicitWidth/Height definiëren de natuurlijke breedte/hoogte van een item als er
// geen breedte of hoogte is gespecificeerd. De onderstaande instelling definieert een
// grootte met voorkeur gebaseerd op zijn inhoud
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 {
Layout.fillHeight: true
level: 1
text: (date < 100000) ? date : i18n("%1 days", Math.round((date-Date.now())/86400000))
}
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: nog te doen... spoedig!
}
}
}
}
}
implicitWidth en implicitHeight
Het eerste deel waar we naar zullen kijken is hoe de breedte en hoogte van onze component te beheren:
Kirigami.AbstractCard {
contentItem: Item {
implicitWidth: delegateLayout.implicitWidth
implicitHeight: delegateLayout.implicitHeight
GridLayout {
id: delegateLayout
...
}
}
}
Kijkend naar onze
Kirigami.AbstractCard
, zijn de eerste eigenschappen die we instellen implicitWidth en implicitHeight. We hebben deze ingesteld op de delegateLayout.implicitWidth
en delegateLayout.implicitHeight
, d.w.z. de implicitWidth
en implicitHeight
van het element GridLayout
. Impliciete breedtes en hoogtes zijn eigenschappen die zijn ingesteld als een soort van standaard, d.w.z. als er geen expliciete breedte of hoogte is ingesteld voor deze componenten. We hebben daarom de implicitWidth
en implicitHeight
van onze
Kirigami.AbstractCard
ingesteld op dat van de onderstaande GridLayout om te verzekeren dat het niet uit de kaart steekt.
Indelingen
De GridLayout is binnen de Item-component die we hebben geleverd voor de eigenschap contentItem. Dit is het Item dat bevat wat getoond zal worden in uw kaart.
We moeten ook een layout voor onze componenten kiezen zodat ze niet op elkaar gestapeld worden. Er zijn drie hoofdtypen waaruit we kunnen kiezen:
- ColumnLayout zet uw componenten verticaal neer, in een enkele kolom
- RowLayout zet uw componenten horizontaal neer, in een enkele rij
- GridLayout zet uw componenten neer in een raster met een compositie naar keuze
Met ColumnLayout en RowLayout, is alles wat we hoeven te doen is onze componenten binnen de component Layout schrijven. Zoals u kunt zien, we gingen voor een GridLayout, die wat meer handwerk vraagt.
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
...
}
Het eerste wat u ziet is ons anchors
. Het verankeringssysteem van QtQuick biedt een bruikbare manier om te verzekeren dat uw componenten gepositioneerd worden in bepaalde delen van een oudercomponent. We hebben onze GridLayout linksboven verankerd en rechts van de ouderkaart, om te verzekeren dat onze inhoud zich uitstrekt over de gehele kaart.
Vervolgens specificeren we de ruimte tussen de rijen en kolommen in ons raster, zodat onze componenten niet opeenstapelen. Kirigami biedt een aantal handige voorgedefinieerde eenheden om voor dit doel te gebruiken:
Kirigami-eenheid | Pixels |
---|---|
smallSpacing | 4px |
largeSpacing | 8px |
gridUnit | 18px |
Notitie
De Visuele ontwerpgroep (VDG) van KDE heeft heel wat meer informatie over de verschillende eenheden gedefinieerd in Plasma en Kirigami op het Human Interface Guidelines.Zoals u zich misschien herinnert, root
is de id van onze
Kirigami.ApplicationWindow
. Het levert de eigenschap
wideScreen
, gebruikt om te bepalen of het huidige apparaatscherm een breed scherm is (d.w.z. een computermonitor of een telefoon in landschap). We gebruiken hier een drievoudige voorwaarde om het aantal kolommen in ons raster te variëren afhankelijk van het scherm dat we gebruiken: als het een breed scherm is, zal het raster 4 kolommen hebben, anders zal het er 2 hebben.
Interne componenten
We konden net drie labels in onze gedelegeerde component aanmaken en dan gereed zijn. Maar dat zou er niet erg mooi uit zien.
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")
}
}
- Links,
Kirigami.Heading
: gebruikt de
date
vanListElement
als een niveau 1 kop. - Midden, ColumnLayout: heeft een
Kirigami.Heading
die de taaknaam toont; een
Kirigami.Separator
, die de horizontale lijn levert; en een
Controls.Label
, die een optionele beschrijving van de taak toont. De laatste twee componenten hebben een eigenschap visible, die controleert of de beschrijving leeg is of niet en de componenten toont afhankelijk van het resultaat van
description.length > 0
. - Rechts, Controls.Button : een knop die iets zal doen... spoedig!
Onze toepassing (app) tot zover
|
|
Dus hier is onze basis kaart!
Met deze stappen hebben we de basis gelegd voor het toevoegen van alle functionaliteit aan uw toepassing.