Pogledi seznama

Pogled seznama vam lahko pomaga pri dinamičnem prikazu številnih komponent.

Pregledi seznamov Listviews vam lahko pomagajo prikazati predmete iz modela na privlačen način. Če želite uporabiti pogled seznama, morate spremljati tri stvari:

  1. model, ki vsebuje podatke, ki jih želite prikazati v pogledu seznama
  2. delegat, ki določa, kako bo vsak element v modelu prikazan
  3. Sam pogled seznama, ki bo prikazoval informacije iz modela v skladu z delegatom

Če želite dodatno pojasnilo, ima dokumentacija Qt informativna stran na to temo.

Osnove modelov in pogledov

Seznamski pogled ima dve bistveni lastnosti, na kateri moramo biti pozorni:

  • model, ki sprejema podatke ali 'id' predmeta, ki nosi podatke
  • delegate, ki sprejema komponento, ki jo bomo uporabili za prikaz podatkov v modelu

Model ni viden, saj vsebuje le podatke. Običajno bo delegat zavit v komponento, tako da jo je mogoče ponovno uporabiti: služi kot načrt za instanciranje vsakega delegata.

Tukaj je primer, ki vsebuje natanko en pogled seznama, en model in enega delegata z uporabo Kirigami.SubtitleDelegate :

import QtQuick
import QtQuick.Controls as Controls
import org.kde.kirigami as Kirigami

Kirigami.ApplicationWindow {
    title: "List of Plasma products"
    width: 600
    height: 400
    pageStack.initialPage: Kirigami.ScrollablePage {
        ListView {
            anchors.fill: parent
            model: plasmaProductsModel
            delegate: listDelegate
        }
        ListModel {
            id: plasmaProductsModel
            ListElement { product: "Plasma Desktop"; target: "desktop" }
            ListElement { product: "Plasma Mobile";  target: "mobile" }
            ListElement { product: "Plasma Bigscreen"; target: "TVs" }
        }
        Component {
            id: listDelegate
            Controls.ItemDelegate {
                width: ListView.view.width
                text: `${model.product} is KDE software developed for ${model.target} stored at index ${model.index} of this list`
            }
        }
    }
}

In popolnoma enak primer, v vrstici:

import QtQuick
import QtQuick.Controls as Controls
import org.kde.kirigami as Kirigami

Kirigami.ApplicationWindow {
    title: "List of Plasma products (inline)"
    width: 600
    height: 400
    pageStack.initialPage: Kirigami.ScrollablePage {
        ListView {
            anchors.fill: parent
            model: ListModel {
                id: plasmaProductsModel
                ListElement { product: "Plasma Desktop"; target: "desktop" }
                ListElement { product: "Plasma Mobile";  target: "mobile" }
                ListElement { product: "Plasma Bigscreen"; target: "TVs" }
            }
            delegate: Controls.ItemDelegate {
                width: ListView.view.width
                text: `${model.product} is KDE software developed for ${model.target} stored at index ${model.index} of this list`
            }
        }
    }
}

Razumevanje modelov

Model vsebuje podatke, ki bodo uporabljeni za zapolnitev pogleda seznama. Različni načini uporabe modelov imajo različne načine za dostop do podatkov:

NAČIN UPORABEKAKO DOSTOPATIKDAJ UPORABITI
Modeli Qt z več kot eno vlogomodel.index, model.someroleV večini primerov
Modeli Qt z eno vlogomodel.index, model.somerole, model.modelDataV večini primerov, za izdelavo prototipov
JavaScript array modelmodel.index, model.modelDataZa izdelavo prototipov
Celoštevilski modelmodel.index, model.modelDataZa izdelavo prototipov

O drugih načinih uporabe modelov lahko preberete v dokumentaciji Qt.

V zgornji tabeli se "modeli Qt" nanašajo tako na modele, specifične za C++, kot je QAbstractListModel, kot na modele, specifične za QML, kot je ListModel. Ta stran učbenika se bo osredotočila samo na modele, specifične za QML. Malo naprej nudimo učbenik za Povezovanje modelov C++ z QML z uporabo QAbstractListModel.

Lastnost model.index je na voljo vsakemu modelu in vsebuje indeks (položaj) vsakega delegata. Zaradi udobja ga je mogoče skrajšati na index.

Zgoraj omenjena lastnost model.somerole je le označba mesta in ni specifična lastnost, ki izhaja iz QML: somerole je lahko katera koli vloga, ki jo definira model. V prvem primeru kode te strani, ki je prikazan nad tabelo, ima model plasmaProductsModel vlogi product in target, do katerih lahko dostopate z model.product oziroma model.target.

Tako kot je model.index mogoče skrajšati v index, lahko vsako lastnost model.somerole skrajšamo samo v somerole (kot product) zaradi udobja, vendar je priporočljivo, da jih spremenite v zahtevane lastnosti :

import QtQuick
import QtQuick.Controls as Controls
import org.kde.kirigami as Kirigami

Kirigami.ApplicationWindow {
    title: "List of Plasma products (shortened with required properties)"
    width: 600
    height: 400
    pageStack.initialPage: Kirigami.ScrollablePage {
        ListView {
            anchors.fill: parent
            model: plasmaProductsModel
            delegate: listDelegate
        }
        ListModel {
            id: plasmaProductsModel
            ListElement { product: "Plasma Desktop"; target: "desktop" }
            ListElement { product: "Plasma Mobile";  target: "mobile" }
            ListElement { product: "Plasma Bigscreen"; target: "TVs" }
        }
        Component {
            id: listDelegate
            Controls.ItemDelegate {
                width: ListView.view.width
                required property string product
                required property string target
                required property int index
                text: `${product} is KDE software developed for ${target} stored at index ${index} of this list`
            }
        }
    }
}

Poleg tega, če model vsebuje samo eno vlogo ali sploh nima nobene vloge, je mogoče do njegovih podatkov dostopati tudi z lastnostjo model.modelData, ki jo je mogoče tudi skrajšati v modelData (in kot taka bi morala biti tudi zahtevana lastnost):

import QtQuick
import QtQuick.Controls as Controls
import org.kde.kirigami as Kirigami


Kirigami.ApplicationWindow {
    title: "List of KDE software"
    width: 400
    height: 400
    pageStack.initialPage: Kirigami.ScrollablePage {
        ListView {
            anchors.fill: parent
            model: kdeSoftwareModel
            delegate: listDelegate
        }
        ListModel {
            id: kdeSoftwareModel
            ListElement { software: "Dolphin" }
            ListElement { software: "Discover" }
            ListElement { software: "KHelpCenter" }
            ListElement { software: "KCalc" }
            ListElement { software: "Ark" }
        }
        Component {
            id: listDelegate
            Controls.ItemDelegate {
                width: ListView.view.width
                required property string modelData
                text: modelData // To se ujema z model.software
            }
        }
    }
}

Za primerjavo, tukaj je videti zgornja koda s poljem JavaScripta, brez vloge:

import QtQuick
import QtQuick.Controls as Controls
import org.kde.kirigami as Kirigami

Kirigami.ApplicationWindow {
    title: "List of KDE software (as JS array)"
    width: 400
    height: 400
    pageStack.initialPage: Kirigami.ScrollablePage {
        ListView {
            anchors.fill: parent
            model: ["Dolphin", "Discover", "KHelpCenter", "KCalc", "Ark"]
            delegate: listDelegate
        }
        Component {
            id: listDelegate
            Controls.ItemDelegate {
                width: ListView.view.width
                required property string modelData
                text: modelData
            }
        }
    }
}

Uporaba celega števila za model je lahko uporabna za zelo specifične primere, namreč izdelavo prototipov in teste:

import QtQuick
import QtQuick.Controls as Controls
import org.kde.kirigami as Kirigami

Kirigami.ApplicationWindow {
    title: "Simple list of indexes"
    width: 400
    height: 400
    pageStack.initialPage: Kirigami.ScrollablePage {
        ListView {
            anchors.fill: parent
            model: 30
            delegate: listDelegate
        }
        Component {
            id: listDelegate
            Controls.ItemDelegate {
                width: ListView.view.width
                required property string modelData
                text: `This delegate's index is: ${modelData}`
            }
        }
    }
}

Razumevanje pogledov in delegatov

Vrnimo se k izvirnemu primeru:

import QtQuick
import QtQuick.Controls as Controls
import org.kde.kirigami as Kirigami

Kirigami.ApplicationWindow {
    title: "List of Plasma products"
    width: 600
    height: 400
    pageStack.initialPage: Kirigami.ScrollablePage {
        ListView {
            // anchors.fill: parent
            model: plasmaProductsModel
            delegate: listDelegate
        }
        ListModel {
            id: plasmaProductsModel
            ListElement { product: "Plasma Desktop"; target: "desktop" }
            ListElement { product: "Plasma Mobile";  target: "mobile" }
            ListElement { product: "Plasma Bigscreen"; target: "TVs" }
        }
        Component {
            id: listDelegate
            Controls.ItemDelegate {
                width: ListView.view.width
                text: `${model.product} is KDE software developed for ${model.target} stored at index ${model.index} of this list`
            }
        }
    }
}

Za razliko od modela (ki vsebuje samo podatke) in delegata Component (ki se prikaže le, ko je instanciran), je pogled vizualna komponenta, ki je takoj instancirana, zato mora imeti bodisi nastavljene dimenzije ali uporabite sidra ali postavitve.

Ker so pogledi običajno seznami vsebine, po kateri bi se uporabnik rad pomikal, ko so dodani na Kirigami.ScrollablePage , pogledi postanejo glavna vsebina z malo oblazinjenja okoli njih in ni potrebe da zapolni stran. Ko je pogled dodan k preprosti strani Kirigami.Page , bo moral pravilno nastaviti svoje dimenzije, preden se prikaže. Z drugimi besedami: na zgornji strani, po kateri se lahko premikate, anchors.fill: parent ni zahtevan; če je bila uporabljena preprosta stran, pa bi bil zahtevan.

Uporabiti je mogoče več pogledov API-jev, nekatere iz Qt in nekatere iz Kirigami. Tu so najpogosteje uporabljeni:

Po drugi strani mora imeti delegat vedno nastavljene dimenzije. Na splošno so njegove mere nastavljene tako, da uporabljajo samo celotno širino pogleda.

Najpogostejša uporaba delegata je znotraj komponente , ki delegata ne instancira takoj. Ko je pogled izdelan, se delegat nato uporabi kot načrt za izdelavo vsakega elementa v pogledu.

Medtem ko lahko naredite svoje komponente po meri, ki jih boste uporabljali kot delegate brez API-jev Qt, specifičnih za delegate (na primer postavitev, ki vsebuje nekaj elementov), ​​QtQuick Controls ponuja API-je za delegate, ki so preprostejši za uporabo:

Če je mogoče, raje uporabite delegate iz Qt toka navzgor.

Poleg teh delegatov Qt ponuja Kirigami svoje ekvivalente z dodano funkcijo podnapisov in ikon:

API, ki se konča z "Delegate", lahko nastavite kot neposrednega delegata pogleda, tako kot v prejšnjih primerih, ki so uporabljali Controls.ItemDelegate:

import QtQuick
import QtQuick.Controls as Controls
import org.kde.kirigami as Kirigami
import org.kde.kirigami.delegates as KD

Kirigami.ApplicationWindow {
    title: "List of Plasma products"
    width: 600
    height: 400
    pageStack.initialPage: Kirigami.ScrollablePage {
        ListView {
            model: plasmaProductsModel
            delegate: listDelegate
        }
        ListModel {
            id: plasmaProductsModel
            ListElement { product: "Plasma Desktop"; target: "desktop" }
            ListElement { product: "Plasma Mobile";  target: "mobile" }
            ListElement { product: "Plasma Bigscreen"; target: "TVs" }
        }
        Component {
            id: listDelegate
            KD.CheckSubtitleDelegate {
                width: ListView.view.width
                text: `${model.product} is KDE software developed for ${model.target}.`
                subtitle: `This delegate is stored at index ${model.index} of this list`
                icon.name: "kde"
            }
        }
    }
}

Tako TitleSubtitle kot IconTitleSubtitle naj bi se uporabljala za preglasitev contentItem delegata Qt, na primer:

import QtQuick
import QtQuick.Controls as Controls
import org.kde.kirigami as Kirigami
import org.kde.kirigami.delegates as KD

Kirigami.ApplicationWindow {
    title: "List of Plasma products"
    width: 600
    height: 400
    pageStack.initialPage: Kirigami.ScrollablePage {
        ListView {
            // anchors.fill: parent
            model: plasmaProductsModel
            delegate: listDelegate
        }
        ListModel {
            id: plasmaProductsModel
            ListElement { product: "Plasma Desktop"; target: "desktop" }
            ListElement { product: "Plasma Mobile";  target: "mobile" }
            ListElement { product: "Plasma Bigscreen"; target: "TVs" }
        }
        Component {
            id: listDelegate
            Controls.ItemDelegate {
                width: ListView.view.width
                text: `${model.product} is KDE software developed for ${model.target}.`
                contentItem: KD.IconTitleSubtitle {
                    title: parent.text
                    subtitle: `This delegate is stored at index ${model.index} of this list`
                    icon.name: "kde"
                }
            }
        }
    }
}

Praktični primer uporabe delegatov Kirigami si lahko ogledate v datoteki ListItemTest v repozitoriju Kirigami.