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 Lijstweergave gekomen. Heel eenvoudig, Lijstweergaven laten u gegevens in een lijst tonen.
Kirigami.CardsListView {
id: layout
model: kountdownModel
delegate: kountdownDelegate
}
Dat lijkt cryptisch, maar geen getob. Laten we bovenaan beginnen.
Het eerste ding dat u zult opmerken, is dat we Kirigami.CardsListView
gebruiken. Dit is een Lijstweergave die ons biedt om gemakkelijk kaarten 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 }
}
Een model definieert de manier waarop invoer van gegevens is gestructureerd. Door naar ons bovenstaande ListElement te kijken kunnen we zien hoe elementen van kountdownModel zijn gestructureerd: ze bevatten een naam, een beschrijving en een datum. De eerste twee zijn gewoon tekenreeksen en de derde is getal die we als plaatshouder gebruiken.
Notitie
Since QML is built on top of JavaScript, many of this language's features are available for use in QML files. However, JavaScript variables have to be prefixed withproperty
in QML.Modellen zijn ook nuttig in hoe ze gewijzigd kunnen worden met gebruik van verschillende methoden. Enige belangrijken zijn:
- ListModelName.append(jsobject uwobject) voegt een JavaScript object toe dat u levert 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.
- ListModelName.get(int index) geeft het JSObject terug op de indexlocatie die u levert.
- ListModelName.remove(int index, int count) verwijdert het JSObject op de geleverde indexlocatie en zoveel na die indexlocatie als u wilt (1 bevat alleen het JSObject op de geleverde index)
- ListModelName.set(int index, jsobject yourobject) wijzigt het item op de geleverde indexlocatie met de waarden geleverd in uwobject. Zelfde regels als met
.append
.
Overdragen
De gedeleerde behandelt hoe de gegevens van uw ListModel getoond zullen worden in de ListView. CardsListView elementen zijn ontworpen met kaart-type gedelegeerden in gedachte en we hebben inderdaad een element Kirigami.AbstractCard
als onze gedelegeerde in het bovenstaande uittreksel gebruikt.
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
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
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 de GridLayout
niet uit de kaart steekt.
Indelingen
De GridLayout
is binnen se component Item
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 indeling 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 kolomRowLayout
zet uw componenten horizontaal neer, in een enkele rijGridLayout
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 raster indeling, 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 anker
. 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 se 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
KDE's Visual Design Group (VDG) has a lot more information about different units defined within Plasma and Kirigami on the Human Interface Guidelines site.We hebben hier ook een voorwaarde om het aantal kolommen in ons raster te variëren afhankelijk van het scherm dat we gebruiken. Als we een breed scherm gebruiken (d.w.z. een computermonitor of een telefoon in landschap) zal het raster 4 kolommen hebben, anders zullen het er 2 zijn.
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 dedate
vanListElement
als een level 1 kop. - Midden,
ColumnLayout
: heeft eenKirigami.Heading
die de taaknaam toont; eenKirigami.Separator
, die de horizontale lijn levert; en eenControls.Label
, die een optionele beschrijving van de taak toont. de laatste twee componenten hebben een eigenschapvisible
, die controleert of de beschrijving leeg is of niet en de componenten toont afhankelijk van het resultaat vandescription.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.