Skip to main content
Passa al contenuto

Layout, ListView e schede

Capire i diversi modi di posizionare le cose in una pagina

Disporre i contenuti

Ora che abbiamo capito come funzionano le pagine, è il momento di aggiungervi qualcosa. Esamineremo una serie di importanti componenti ed elementi di layout che saranno utili durante la progettazione della nostra app.

Alla fine di questa sezione avrai un'applicazione dall'aspetto ordinato.

Viste a elenco

Se hai mai utilizzato Discover, NeoChat o le Impostazioni di sistema di Plasma, ti sarai imbattuto in una ListView. Molto semplicemente, ti consente di visualizzare i dati in un elenco.

pageStack.initialPage: Kirigami.ScrollablePage {
    // ...
    Kirigami.CardsListView {
       id: cardsView
        model: kountdownModel
        delegate: kountdownDelegate
    }
}

Sembra criptico, ma non preoccuparti. Cominciamo dall'inizio.

Aggiungiamo questo componente all'interno del nostro Kirigami.ScrollablePage dall'ultimo tutorial.

Stiamo utilizzando Kirigami.CardsListView, che è un ListView che ci consente di visualizzare facilmente le schede in un elenco. Tuttavia, i ListView sono progettati per mostrare i dati presi da un modello, per popolarsi automaticamente da un insieme di dati a cui li indichiamo. È qui che entra in gioco la proprietà model: in questo esempio punta a "kountdownModel".

Modello

Kirigami.ApplicationWindow {
    // ...
    ListModel {
        id: kountdownModel
        // Ciascun ListElement è un elemento della lista, contenente le informazioni
        ListElement {
            name: "Dog birthday!!"
            description: "Big doggo birthday blowout."
            date: 100
        }
    }
    // ...
}

Aggiungiamo il nostro kountdownModel all'interno di Kirigami.ApplicationWindow dall'ultimo tutorial.

Un modello definisce il modo in cui è strutturata l'immissione di dati. Il nostro kountdownModel sarà composto da un solo elemento per ora. Osservando il nostro ListElement sopra, possiamo vedere come sono strutturati i dati del nostro kountdownModel: contiene un nome, una descrizione e una data. Questo non è scolpito nella pietra e potresti avere diversi tipi di dati nel tuo modello. I primi due sono solo stringhe e il terzo è un numero che utilizziamo come segnaposto.

I modelli sono utili anche nel modo in cui possono essere modificati mediante l'uso di diversi metodi. Alcuni importanti sono:

Delegati

Mentre il nostro kountdownModel contiene i dati che saranno visualizzati, il nostro kountdownDelegate gestirà il modo in cui i dati saranno visualizzati in ListView. Per questo usiamo un Kirigami.CardsListView progettato per visualizzare i delegati di tipo scheda e tali delegati saranno rappresentati visivamente per mezzo di un Kirigami.AbstractCard.

I delegati ricevono automaticamente le proprietà delle istanze ListElement che abbiamo specificato nel nostro modello. Possiamo quindi semplicemente fare riferimento alle loro proprietà "nome", "descrizione" e "data" come se fossero variabili convenzionali all'interno del nostro delegato.

Costruire la tessera del delegato

Il Componente che rappresenterà il nostro delegato può essere aggiunto all'interno della nostra Kirigami.ApplicationWindow. Controlleremo quindi cosa fa ciascuna parte del nostro componente delegato.

Kirigami.ApplicationWindow {
    // ...
    Component {
        id: kountdownDelegate
        Kirigami.AbstractCard {
            contentItem: Item {
                // implicitWidth /Height definiscono la larghezza e l'altezza naturali di un
                // elemento, se queste non vengono specificate. L'impostazione qui sotto definisce
                // la dimensione preferita del componente in base al suo contenuto.
                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: da fare... presto!!
                    }
                }
            }
        }
    }
    // ...
}

implicitWidth e implicitHeight

La prima parte a cui daremo un'occhiata è come gestire la larghezza e l'altezza del nostro componente:

Kirigami.AbstractCard {
    contentItem: Item {
        implicitWidth: delegateLayout.implicitWidth
        implicitHeight: delegateLayout.implicitHeight
        GridLayout {
            id: delegateLayout
            // ...
        }
    }
}

Osservando la nostra Kirigami.AbstractCard, le prime proprietà che impostiamo sono implicitWidth e ImplicitHeight. Li abbiamo impostati su delegateLayout.implicitWidth e delegateLayout.implicitHeight, ovvero implicitWidth e implicitHeight dell'elemento GridLayout.

Le larghezze e le altezze implicite sono proprietà disponibili in qualsiasi Item che funzionano come suggerimenti e sono impostate come predefinite o come fallback, se non esiste una larghezza o un'altezza esplicita impostata per questi componenti. Questi valori sono 0x0 per impostazione predefinita, quindi è molto importante definirli nei componenti grezzi dell'articolo come fatto sopra.

Qui abbiamo impostato implicitWidth e implicitHeight della nostra Kirigami.AbstractCard su quella del GridLayout di seguito per garantire che non fuoriesca dalla scheda. In questo modo la scheda occupa tutto lo spazio necessario per il suo contenuto.

Disposizioni

Il GridLayout è all'interno del componente Item che abbiamo fornito per la proprietà contentItem. Questo è l'Articolo che contiene ciò che sarà visualizzato nella tua scheda.

Dobbiamo anche scegliere un layout per i nostri componenti in modo che non si accumulino uno sopra l'altro. Esistono tre tipologie principali tra cui possiamo scegliere:

  • ColumnLayout dispone i componenti verticalmente, in un'unica colonna
  • RowLayout dispone i componenti orizzontalmente, in un'unica riga
  • GridLayout dispone i tuoi componenti in una griglia con una composizione a tua scelta

With ColumnLayout and RowLayout, all we have to do is write our components inside the Layout component. Come puoi vedere, abbiamo optato per un GridLayout, che comporta un po' più di lavoro manuale.

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 prima cosa che vedi sono le nostre "ancore". Il sistema di ancoraggio di QtQuick fornisce un modo utile per assicurarsi che i componenti siano posizionati in determinate parti di un componente principale. Abbiamo ancorato il nostro GridLayout a sinistra, in alto e a destra della scheda principale, assicurando che i nostri contenuti si estendano su tutta la scheda.

Successivamente specifichiamo la spaziatura tra le righe e le colonne all'interno della nostra griglia, in modo che i nostri componenti non si accumulino. Kirigami fornisce una serie di utili unità predefinite da utilizzare per questo scopo:

Unità in KirigamiPixel
smallSpacing4px
largeSpacing8px
gridUnit18px

Come forse ricorderete, root è l'id della nostra Kirigami.ApplicationWindow. Fornisce la proprietà wideScreen, utilizzata per determinare se lo schermo del dispositivo corrente è widescreen (cioè il monitor di un computer o un telefono in orizzontale). Usiamo un condizionale ternario qui per variare il numero di colonne nella nostra griglia a seconda dello schermo che stiamo utilizzando: se è un widescreen, la griglia avrà 4 colonne, altrimenti ne avrà 2.

Componenti interni

Potremmo semplicemente creare tre etichette all'interno del nostro componente delegato e concludere la giornata, ma non sembrerebbe particolarmente carino. Utilizzeremo alcuni componenti più convenienti:

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")
    }
}
Come appare la scheda personalizzata

Come appare la scheda personalizzata

  • A sinistra, Kirigami.Heading: utilizza la "data" di "ListElement" come intestazione di livello 1.
  • Al centro, ColumnLayout: ha un Kirigami.Heading che visualizza il nome dell'attività; un Kirigami.Separator, che fornisce la linea orizzontale; e un Controls.Label, che visualizza la descrizione facoltativa di un'attività. Gli ultimi due componenti hanno una proprietà visible, che controlla se la descrizione è vuota o meno e visualizza i componenti in base al risultato di description.length > 0.
  • Giusto, Controls.Button: un pulsante che farà qualcosa... presto!

Il nostro programma finora

Main.qml:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls as Controls
import org.kde.kirigami as Kirigami

Kirigami.ApplicationWindow {
    id: root

    width: 400
    height: 300

    title: i18nc("@title:window", "Day Kountdown")

    // ListModel needed for ListView, contains elements to be displayed
    ListModel {
        id: kountdownModel
        // Each ListElement is an element on the list, containing information
        ListElement {
            name: "Dog birthday!!"
            description: "Big doggo birthday blowout."
            date: 100
        }
    }

    Component {
        id: kountdownDelegate
        Kirigami.AbstractCard {
            contentItem: Item {
                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 determines the size of the heading
                        level: 1
                        text: date
                    }

                    // Layout for positioning elements vertically
                    ColumnLayout {
                        Kirigami.Heading {
                            Layout.fillWidth: true
                            level: 2
                            text: name
                        }
                        // Horizontal rule
                        Kirigami.Separator {
                            Layout.fillWidth: true
                            visible: description.length > 0
                        }
                        // Labels contain text
                        Controls.Label {
                            Layout.fillWidth: true
                            // Word wrap makes text stay within box and shift with size
                            wrapMode: Text.WordWrap
                            text: description
                            visible: description.length > 0
                        }
                    }
                    Controls.Button {
                        Layout.alignment: Qt.AlignRight
                        // Column spanning within grid layout (vertically in this case)
                        Layout.columnSpan: 2
                        text: i18n("Edit")
                        //onClicked: to be done...
                    }
                }
            }
        }
    }

    pageStack.initialPage: Kirigami.ScrollablePage {
        title: i18nc("@title", "Kountdown")

        // List view for card elements
        Kirigami.CardsListView {
            id: cardsView
            // Model contains info to be displayed
            model: kountdownModel
            // Delegate is how the information will be presented in the ListView
            delegate: kountdownDelegate
        }
    }
}

Schermata dell'aspetto del programma al termine di questa lezione

Ecco quindi una scheda basilare!

Con questi passaggi, adesso abbiamo gettato le basi per aggiungere tutte le funzionalità al nostro programma.