Dispositions, vues en liste et cartes
Mise en page de votre contenu
Maintenant que nous comprenons le fonctionnement des pages, il est temps d'ajouter des éléments aux nôtres. Nous allons passer en revue un certain nombre de composants et d'éléments de mise en page importants qui nous seront utiles lors de la conception de notre application.
Ne soyez pas effrayé par les gros morceaux de code ! Nous allons passer en revue tout ce que nous n'avons pas encore abordé et à la fin de cette section, vous aurez une application tout à fait soignée.
Vues en liste
Si vous avez déjà utilisé Discover, NeoChat ou les configuration du système Plasma, vous avez forcément rencontré un affichage en liste. Ces derniers vous permettent tout simplement d'afficher des données dans une liste.
Kirigami.CardsListView {
id: layout
model: kountdownModel
delegate: kountdownDelegate
}
Cela semble mystérieux mais ne vous inquiétez pas. Commençons par le début.
La première chose que vous remarquerez est que nous utilisons « Kirigami.CardsListView ». Il s'agit d'un objet « ListView » nous permettant d'afficher facilement des cartes dans une liste. Cependant, ces objets « ListViews » sont conçus pour afficher des données provenant d'un modèle - pour se remplir automatiquement à partir d'un ensemble de données que nous lui indiquons. C'est là que la propriété « model » intervient : dans cet exemple, elle pointe vers « kountdownModel. »
Modèle
ListModel {
id: kountdownModel
// Chaque « ListElement » est un élément de la liste, contenant des informations.
ListElement { name: "Dog birthday!!"; description: "Big doggo birthday blowout."; date: 100 }
}
Un modèle définit la manière dont une entrée de données est structurée. En regardant notre objet « ListElement » ci-dessus, nous pouvons voir comment les éléments de l'objet « kountdownModel » sont structurés : ils contiennent un nom, une description et une date. Les deux premiers sont simplement des chaînes de caractères et le troisième est un nombre que nous utilisons comme caractère de remplacement.
Note
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.Les modèles sont également utiles dans la mesure où ils peuvent être modifiés grâce à l'utilisation de plusieurs méthodes. En voici les plus importants :
- La méthode « ListModelName.append(jsobject yourobject) » ajoute un objet JavaScript que vous fournissez à l'objet « ListModel » et le place après le dernier élément du modèle. Pour que cela se réalise correctement, vous devez fournir un objet JavaScript avec les propriétés correctes et les types de données correspondants.
- ListModelName.get(int index) renvoie l'objet « JSObject » à l'emplacement de l'index que vous avez fourni.
- La fonction « ListModelName.remove(int index, int count) » supprime l'objet « JSObject » à l'emplacement de l'index fourni, et autant après cet emplacement d'index que vous le souhaitez (1 adresse seulement l'objet « JSObject » à l'indice fourni).
- La fonction « ListModelName.set(int index, jsobject yourobject) » modifie l'élément à l'emplacement de l'index fourni avec les valeurs fournies dans « yourobject ». Les mêmes règles s'appliquent avec « .append ».
Déléguer
Le délégué gère la façon dont les données de votre objet « ListModel » seront affichées dans l'objet « ListView ». Les éléments « CardsListView » sont conçus avec des délégués de type carte en tête et nous avons effectivement utilisé un élément « Kirigami.AbstractCard » comme notre délégué comme indiqué dans l'extrait ci-dessus.
Les délégués reçoivent automatiquement les propriétés des objets « ListElement » que nous avons spécifié dans notre modèle. Nous pouvons donc simplement se référer aux propriétés « name », « description » et « date » de nos objets « ListElement », comme si elles étaient une variable conventionnelle dans notre délégué.
Construction de notre carte déléguée
Component {
id: kountdownDelegate
Kirigami.AbstractCard {
contentItem: Item {
// implicitWidth/Height définissent la largeur/hauteur naturelle d'un élément si aucune
// largeur ou hauteur n'est spécifiée. Le paramètre ci-dessous définit la taille
// préférée d'un composant préférée d'un composant en fonction de son contenu.
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 : à faire... bientôt !
}
}
}
}
}
implicitWidth et implicitHeight
Kirigami.AbstractCard {
contentItem: Item {
implicitWidth: delegateLayout.implicitWidth
implicitHeight: delegateLayout.implicitHeight
GridLayout {
id: delegateLayout
...
}
}
}
En regardant notre « Kirigami.AbstractCard », les premières propriétés que nous définissons sont « implicitWidth » et « implicitHeight ». Nous leur avons attribué les valeurs « delegateLayout.implicitWidth » et « delegateLayout.implicitHeight », c'est-à-dire les valeurs « implicitWidth » et « implicitHeight » de l'élément « GridLayout ». Les largeurs et hauteurs implicites sont des propriétés définies par défaut, c'est-à-dire si aucune largeur ou hauteur explicite ne sont définies pour ces composants. Nous avons donc défini les propriétés « implicitWidth » et « implicitHeight » de notre « Kirigami.AbstractCard » selon celles de l'élément « GridLayout » ci-dessous pour nous assurer que ce dernier ne déborde pas de la carte.
Dispositions
Le « GridLayout » se trouve à l'intérieur du composant « Item » que nous avons fourni pour la propriété « contentItem ». Il s'agit de l'élément contenant ce qui sera affiché dans votre carte.
Nous devons également choisir une disposition pour nos composants afin qu'ils ne s'empilent pas les uns sur les autres. Il existe trois types principaux parmi lesquels nous pouvons choisir :
- « ColumnLayout » présente vos composants verticalement, dans une seule colonne.
- « RowLayout » dispose vos composants horizontalement, sur une seule ligne.
- « GridLayout » dispose vos composants dans une grille avec une disposition de votre choix.
Avec les paramètres « ColumnLayout » et « RowLayout », tout ce que nous avons à faire est d'écrire nos composants à l'intérieur du composant « Layout ». Comme vous pouvez le constater, nous avons opté pour une disposition en grille, ce qui implique un peu plus de travail manuel.
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
...
}
La première chose que vous voyez est notre « ancre ». Le système d'ancrage de QtQuick fournit un moyen utile de s'assurer que vos composants sont positionnés sur certaines parties d'un composant parent. Nous avons ancré notre objet « GridLayout » à gauche, en haut et à droite de la carte parente, en nous assurant que notre contenu s'étende sur la totalité de la carte.
Ensuite, nous spécifions l'espacement entre les lignes et les colonnes de notre grille, pour que nos composants ne s'entassent pas. Kirigami fournit un certain nombre d'unités pratiques prédéfinies à utiliser pour cela :
Unité de Kirigami | Pixels |
---|---|
Petit espacement | 4 px |
Espacement large | 8 px |
Unité de grille | 18 px |
Note
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.Nous avons également utilisé une conditionnelle ici pour faire varier le nombre de colonnes de notre grille selon l'écran que nous utilisons. Si nous utilisons un écran large (c'est-à-dire un écran d'ordinateur ou un téléphone en mode paysage), la grille aura 4 colonnes, sinon elle en aura 2.
Composants intérieurs
Nous pourrions simplement créer trois étiquettes au sein de notre composant délégué et l'appeler une journée. Mais cela n'aura pas un bel aspect.
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")
}
}
- À gauche, « Kirigami.Heading » : utilise la « date » de l'« ListElement » comme un titre de niveau 1.
- Au milieu, « ColumnLayout » : possède un objet « Kirigami.Heading » affichant le nom de la tâche, un objet « Kirigami.Separator » fournissant la ligne horizontale et un objet « Controls.Label » affichant la description optionnelle d'une tâche. Les deux derniers composants possèdent une propriété « visible », vérifiant si la description est vide ou non et affiche les composants en fonction du résultat de la condition « description.length > 0 ».
- A droite, « Controls.Button » : un bouton qui fera quelque chose... bientôt !
Notre application jusqu'à présent
Ainsi, ceci est notre carte basique !
Avec ces étapes, nous avons maintenant posé les bases pour ajouter toutes les fonctionnalités à notre application.