Auf dieser Seite

Modelle und Ansichten in Qt Quick

Die meisten Anwendungen müssen Daten aufbereiten und anzeigen. „ Qt Quick “ nutzt die Konzepte von Modellen, Ansichten und Delegaten zur Datenanzeige. Diese modularisieren die Visualisierung von Daten, um dem Entwickler oder Designer die Kontrolle über die verschiedenen Aspekte der Daten zu ermöglichen. Ein Entwickler kann eine Listenansicht mit nur geringen Änderungen an den Daten gegen eine Rasteransicht austauschen. Ebenso ermöglicht die Kapselung einer Dateninstanz in einem Delegaten dem Entwickler, festzulegen, wie die Daten dargestellt oder verarbeitet werden sollen.

Diagramm, das den Datenfluss zu den Komponenten „Model“, „View“ und „Delegate“ veranschaulicht

  • Modell – enthält die Daten und deren Struktur. Es gibt verschiedene QML-Typen zum Erstellen von Modellen.
  • Ansicht – ein Container, der die Daten anzeigt. Die Ansicht kann die Daten in einer Liste oder einem Raster darstellen.
  • Delegat – legt fest, wie die Daten in der Ansicht dargestellt werden sollen. Das Delegat nimmt jede Dateneinheit aus dem Modell auf und kapseln sie. Der Zugriff auf die Daten erfolgt über das Delegat. Das Delegat kann Daten auch in bearbeitbare Modelle zurückschreiben (z. B. im `onAccepted`-Handler eines ` TextField`).

Um Daten zu visualisieren, binden Sie die Eigenschaft „ model “ der Ansicht an ein Modell und die Eigenschaft „ delegate “ an eine Komponente oder einen anderen kompatiblen Typ.

Anzeigen von Daten mit Ansichten

Ansichten sind Container für Sammlungen von Elementen. Sie verfügen über zahlreiche Funktionen und lassen sich an stilistische oder verhaltensbezogene Anforderungen anpassen.

Im Basisumfang der grafischen Typen von „ Qt Quick “ ist eine Reihe von Standardansichten enthalten:

Diese Typen verfügen über Eigenschaften und Verhaltensweisen, die für den jeweiligen Typ spezifisch sind. Weitere Informationen finden Sie in der jeweiligen Dokumentation.

Darüber hinaus Qt Quick Controls enthält einige zusätzliche Ansichten und Delegaten, deren Darstellung an den Anwendungsstil angepasst ist, zum Beispiel „ HorizontalHeaderView “ und „ VerticalHeaderView “.

Ansichten gestalten

Ansichten lassen sich mithilfe von Dekorationseigenschaften wie header, footer und section visuell anpassen. Durch die Bindung eines Objekts – in der Regel eines anderen visuellen Objekts – an diese Eigenschaften lassen sich die Ansichten dekorieren. Eine Fußzeile kann beispielsweise einen Rectangle -Typ enthalten, der Rahmen anzeigt, oder eine Kopfzeile, die ein Logo über der Liste anzeigt.

Angenommen, ein bestimmter Verein möchte seine Mitgliederliste mit seinen Markenfarben gestalten. Eine Mitgliederliste befindet sich in einem „ model “, und das „ delegate “ zeigt den Inhalt des Modells an.

ListModel {
    id: nameModel
    ListElement { name: "Alice" }
    ListElement { name: "Bob" }
    ListElement { name: "Jane" }
    ListElement { name: "Harry" }
    ListElement { name: "Wendy" }
}
Component {
    id: nameDelegate
    Text {
        required property string name
        text: name
        font.pixelSize: 24
        width: ListView.view.width
    }
}

Der Verein kann die Mitgliederliste gestalten, indem er visuelle Objekte an die Eigenschaften „ header “ und „ footer “ bindet. Das visuelle Objekt kann inline, in einer anderen Datei oder in einem Typ „ Component “ definiert werden.

ListView {
    anchors.fill: parent
    clip: true
    model: nameModel
    delegate: nameDelegate
    header: bannercomponent
    footer: Rectangle {
        width: parent.width; height: 30;
        gradient: clubcolors
    }
    highlight: Rectangle {
        color: "lightgray"
    }
}

Component {     //instantiated when header is processed
    id: bannercomponent
    Rectangle {
        id: banner
        width: parent.width; height: 50
        gradient: clubcolors
        border {color: "#9EDDF2"; width: 2}
        Text {
            anchors.centerIn: parent
            text: "Club Members"
            font.pixelSize: 32
        }
    }
}
Gradient {
    id: clubcolors
    GradientStop { position: 0.0; color: "#8EE2FE"}
    GradientStop { position: 0.66; color: "#7ED2EE"}
}

Liste mit der hervorgehobenen Überschrift „Clubmitglieder“ über Alice, Bob, Jane, Harry, Wendy

Maus- und Touch-Verarbeitung

Die Ansichten verarbeiten das Ziehen und Wischen ihres Inhalts, jedoch nicht die Touch-Interaktion mit den einzelnen Delegaten. Damit die Delegaten auf Touch-Eingaben reagieren können, z. B. um die Eigenschaft ` currentIndex` zu setzen, muss der Delegat ein ` MouseArea ` mit der entsprechenden Touch-Verarbeitungslogik bereitstellen.

Beachten Sie, dass bei einer Einstellung von ` highlightRangeMode ` auf ` StrictlyEnforceRange ` der `currentIndex` durch das Ziehen/Wischen der Ansicht beeinflusst wird, da die Ansicht stets sicherstellt, dass der ` currentIndex ` innerhalb des festgelegten Hervorhebungsbereichs liegt.

ListView-Abschnitte

ListView Der Inhalt kann in Abschnitte gruppiert werden, wobei zugehörige Listenelemente entsprechend ihrer Abschnitte beschriftet werden. Darüber hinaus können die Abschnitte mit Delegaten gestaltet werden.

Eine Liste kann eine Liste enthalten, in der die Namen von Personen und das Team, dem die jeweilige Person angehört, aufgeführt sind.

ListModel {
    id: nameModel
    ListElement { name: "Alice"; team: "Crypto" }
    ListElement { name: "Bob"; team: "Crypto" }
    ListElement { name: "Jane"; team: "QA" }
    ListElement { name: "Victor"; team: "QA" }
    ListElement { name: "Wendy"; team: "Graphics" }
}
Component {
    id: nameDelegate
    Text {
        required property string name
        text: name;
        font.pixelSize: 24
        anchors.left: parent.left
        anchors.leftMargin: 2
    }
}

Der Typ „ ListView “ verfügt über die angehängte Eigenschaft „ section “, mit der benachbarte und verwandte Typen zu einem Abschnitt zusammengefasst werden können. Die Eigenschaft „ section.property “ legt fest, welche Eigenschaft des Listentyps als Abschnitte verwendet werden soll. Die Eigenschaft „ section.criteria “ kann bestimmen, wie die Abschnittsnamen angezeigt werden, und die Eigenschaft „ section.delegate “ ähnelt der Delegate-Eigenschaft der Ansichten.

ListView {
    anchors.fill: parent
    model: nameModel
    delegate: nameDelegate
    focus: true
    highlight: Rectangle {
        color: "lightblue"
        width: parent.width
    }
    section {
        property: "team"
        criteria: ViewSection.FullString
        delegate: Rectangle {
            color: "#b0dfb0"
            width: parent.width
            height: childrenRect.height + 4
            Text { anchors.horizontalCenter: parent.horizontalCenter
                font.pixelSize: 16
                font.bold: true
                text: section
            }
        }
    }
}

Nach Teams gruppierte Liste: Krypto mit Alice und Bob, Qualitätssicherung mit Jane und Victor, Grafik mit Wendy

Ansichtsdelegaten

Ansichten benötigen einen Delegaten, um ein Element in einer Liste visuell darzustellen. Eine Ansicht visualisiert jedes Element der Liste gemäß der vom Delegaten definierten Vorlage. Auf Elemente in einem Modell kann sowohl über die Eigenschaft „ index “ als auch über die Eigenschaften des Elements zugegriffen werden.

Component {
    id: petdelegate
    Text {
        id: label
        font.pixelSize: 24
        text: index === 0 ? type + " (default)" : type

        required property int index
        required property string type
    }
}

Liste mit den Einträgen „Katze“ (Standard), „Hund“, „Maus“, „Kaninchen“ und „Pferd“

Positionierung von Ansichtsdelegaten

Der Ansichtstyp bestimmt, wie die Elemente positioniert werden. „ ListView “ positioniert die Elemente in einer geraden Linie, abhängig von der Eigenschaft „ orientation “, während eine „ GridView “ sie in einem zweidimensionalen Raster anordnet. Es wird nicht empfohlen, direkt an „ x “ und „ y “ zu binden, da das Layoutverhalten der Ansicht stets Vorrang vor jeglicher Positionsbindung hat.

Zugriff auf Ansichten und Modelle über Delegaten

GridView.view Auf die Listenansicht, an die der Delegat gebunden ist, kann vom Delegaten aus über die Eigenschaft „ ListView.view “ zugegriffen werden. Ebenso steht den Delegaten die Eigenschaft „ GridView “ zur Verfügung. Das entsprechende Modell und seine Eigenschaften sind daher über „ ListView.view.model “ zugänglich. Darüber hinaus sind auch alle im Modell definierten Signale oder Methoden zugänglich.

Dieser Mechanismus ist nützlich, wenn Sie beispielsweise denselben Delegaten für mehrere Ansichten verwenden möchten, dabei aber möchten, dass Dekorationen oder andere Merkmale für jede Ansicht unterschiedlich sind, und Sie möchten, dass diese unterschiedlichen Einstellungen als Eigenschaften der jeweiligen Ansichten vorliegen. Ebenso könnte es von Interesse sein, auf bestimmte Eigenschaften des Modells zuzugreifen oder diese anzuzeigen.

Im folgenden Beispiel zeigt der Delegat die Eigenschaft „language“ des Modells an, und die Farbe eines der Felder hängt von der Eigenschaft „fruit_color“ der Ansicht ab.

Rectangle {
     width: 200; height: 200

    ListModel {
        id: fruitModel
        property string language: "en"
        ListElement {
            name: "Apple"
            cost: 2.45
        }
        ListElement {
            name: "Orange"
            cost: 3.25
        }
        ListElement {
            name: "Banana"
            cost: 1.95
        }
    }

    Component {
        id: fruitDelegate
        Row {
            id: fruit
            required property string name
            required property real cost
            Text {
                text: " Fruit: " + fruit.name
                color: fruit.ListView.view.fruit_color
            }
            Text {
                text: " Cost: $" + fruit.cost
            }
            Text {
                text: " Language: " + fruit.ListView.view.model.language
            }
        }
    }

    ListView {
        property color fruit_color: "green"
        model: fruitModel
        delegate: fruitDelegate
        anchors.fill: parent
    }
}

Modelle

Daten werden dem Delegaten über benannte Datenrollen bereitgestellt, an die sich der Delegat binden kann. Hier ist ein „ ListModel “ mit zwei Rollen, „type“ und „age“, sowie ein „ ListView “ mit einem Delegaten, der sich an diese Rollen bindet, um deren Werte anzuzeigen:

import QtQuick

Item {
    width: 200
    height: 250

    ListModel {
        id: myModel
        ListElement { type: "Dog"; age: 8; noise: "meow" }
        ListElement { type: "Cat"; age: 5; noise: "woof" }
    }

    component MyDelegate : Text {
        required property string type
        required property int age
        text: type + ", " + age
        // WRONG: Component.onCompleted: () => console.log(noise)
        // The above line would cause a ReferenceError
        // as there is no required property noise,
        // and the presence of the required properties prevents
        // noise from being injected into the scope
    }

    ListView {
        anchors.fill: parent
        model: myModel
        delegate: MyDelegate {}
    }
}

In den meisten Fällen sollten Sie Pflicht-Eigenschaften verwenden, um Modelldaten an Ihre Delegaten zu übergeben. Wenn ein Delegat Pflicht-Eigenschaften enthält, prüft die QML-Engine, ob der Name einer Pflicht-Eigenschaft mit dem einer Modellrolle übereinstimmt. Ist dies der Fall, wird diese Eigenschaft an den entsprechenden Wert aus dem Modell gebunden.

In seltenen Sonderfällen möchten Sie möglicherweise die Modelleigenschaften nicht als erforderliche Eigenschaften, sondern über den QML-Kontext übergeben. Wenn in Ihrem Delegaten keine erforderlichen Eigenschaften vorhanden sind, werden die benannten Rollen als Kontexteigenschaften bereitgestellt:

import QtQuick

Item {
    width: 200; height: 250

    ListModel {
        id: myModel
        ListElement { type: "Dog"; age: 8 }
        ListElement { type: "Cat"; age: 5 }
    }

    Component {
        id: myDelegate
        Text { text: type + ", " + age }
    }

    ListView {
        anchors.fill: parent
        model: myModel
        delegate: myDelegate
    }
}

Kontext-Eigenschaften sind für Werkzeuge nicht sichtbar und verhindern, dass der „Qt Quick “-Compiler Ihren Code optimiert. Sie erschweren es, die spezifischen Daten zu ermitteln, die Ihr Delegat erwartet. Es gibt keine Möglichkeit, den QML-Kontext explizit aus QML heraus zu füllen. Wenn Ihre Komponente erwartet, dass Daten über den QML-Kontext übergeben werden, können Sie diesen nur an Stellen verwenden, an denen der richtige Kontext auf native Weise bereitgestellt wird. Dies kann Ihr eigener C++-Code oder die spezifischen Implementierungen umgebender Elemente sein. Umgekehrt können erforderliche Eigenschaften auf verschiedene Weise aus QML heraus oder über native Mittel gesetzt werden. Daher verringert die Übergabe von Daten über den QML-Kontext die Wiederverwendbarkeit Ihrer Komponenten.

Wenn es einen Namenskonflikt zwischen den Eigenschaften des Modells und den Eigenschaften des Delegaten gibt, kann stattdessen mit dem qualifizierten Modellnamen auf die Rollen zugegriffen werden. Wenn beispielsweise ein Typ „ Text “ (nicht erforderliche) Eigenschaften „type“ oder „age“ hätte, würde der Text im obigen Beispiel diese Eigenschaftswerte anstelle der Werte für „type“ und „age“ aus dem Modellelement anzeigen. In diesem Fall hätten die Eigenschaften stattdessen als „ model.type “ und „ model.age “ referenziert werden können, um sicherzustellen, dass der Delegat die Eigenschaftswerte aus dem Modellelement anzeigt. Damit dies funktioniert, müssen Sie in Ihrem Delegaten eine „ model “-Eigenschaft als erforderlich festlegen (es sei denn, Sie verwenden Kontexteigenschaften).

Dem Delegaten steht außerdem eine spezielle Indexrolle zur Verfügung, die den Index des Elements im Modell enthält. Beachten Sie, dass dieser Index auf -1 gesetzt wird, wenn das Element aus dem Modell entfernt wird. Wenn Sie eine Bindung an die Index-Rolle herstellen, stellen Sie sicher, dass die Logik die Möglichkeit berücksichtigt, dass der Index -1 ist, d. h., dass das Element nicht mehr gültig ist. (Normalerweise wird das Element in Kürze zerstört, aber es ist möglich, die Zerstörung des Delegaten in einigen Ansichten über die angehängte Eigenschaft „ delayRemove “ zu verzögern.)

Beachten Sie, dass Sie als Modell sowohl Ganzzahlen als auch Arrays verwenden können:

Repeater {
    model: 5
    Text {
        required property int modelData
        text: modelData
    }
}
Repeater {
    model: ["one", "two", "three"]
    Text {
        required property string modelData
        text: modelData
    }
}

Solche Modelle stellen jeder Instanz des Delegaten einen einzelnen, anonymen Datenwert zur Verfügung. Der Zugriff auf diesen Datenwert ist der Hauptgrund für die Verwendung von „modelData“, doch auch andere Modelle stellen „modelData“ bereit.

Das über die Rolle „model“ bereitgestellte Objekt verfügt über eine Eigenschaft mit einem leeren Namen. Diese anonyme Eigenschaft enthält die „modelData“. Darüber hinaus verfügt das über die Rolle „model“ bereitgestellte Objekt über eine weitere Eigenschaft namens „modelData“. Diese Eigenschaft ist veraltet und enthält ebenfalls die „modelData“.

Zusätzlich zur „model“-Rolle wird eine „modelData“-Rolle bereitgestellt. Die „modelData“-Rolle enthält dieselben Daten wie die „modelData“-Eigenschaft und die anonyme Eigenschaft des über die „model“-Rolle bereitgestellten Objekts.

Die Unterschiede zwischen der „model“-Rolle und den verschiedenen Möglichkeiten, auf „modelData“ zuzugreifen, sind wie folgt:

  • Bei Modellen ohne benannte Rollen (wie z. B. Ganzzahlen oder ein Array von Zeichenketten) werden die Daten über die „modelData“-Rolle bereitgestellt. In diesem Fall enthält die „modelData“-Rolle nicht unbedingt ein Objekt. Im Fall eines Integer-Modells würde sie eine Ganzzahl enthalten (den Index des aktuellen Modellelements). Im Fall eines Arrays von Zeichenketten würde sie eine Zeichenkette enthalten. Die „model“-Rolle enthält weiterhin ein Objekt, jedoch ohne Eigenschaften für benannte Rollen. „model“ enthält jedoch nach wie vor seine üblichen „modelData“- und „anonymous“-Eigenschaften.
  • Wenn das Modell nur eine benannte Rolle hat, enthält die „modelData“-Rolle dieselben Daten wie die benannte Rolle. Es handelt sich nicht unbedingt um ein Objekt, und es enthält die benannte Rolle nicht wie üblich als benannte Eigenschaft. Die „model“-Rolle enthält in diesem Fall weiterhin ein Objekt mit der benannten Rolle als Eigenschaft sowie die „modelData“- und anonymen Eigenschaften.
  • Bei Modellen mit mehreren Rollen wird die Rolle „modelData“ nur als erforderliche Eigenschaft bereitgestellt, nicht als Kontexteigenschaft. Dies ist auf die Abwärtskompatibilität mit älteren Versionen von Qt zurückzuführen.

Die anonyme Eigenschaft auf „model“ ermöglicht es Ihnen, Delegaten sauber zu schreiben, die sowohl ihre Modelldaten als auch den Rollennamen, auf den sie reagieren sollen, als Eigenschaften von außen erhalten. Sie können ein Modell ohne oder mit nur einer benannten Rolle und einer leeren Zeichenkette als Rolle bereitstellen. Dann führt eine Bindung, die einfach auf „ model[role] “ zugreift, das aus, was Sie erwarten. Für diesen Fall müssen Sie keinen speziellen Code hinzufügen.

Hinweis: Auf die Rollen „model“, „index“ und „modelData“ kann nicht zugegriffen werden, wenn der Delegat erforderliche Eigenschaften enthält, es sei denn, er verfügt ebenfalls über erforderliche Eigenschaften mit übereinstimmenden Namen.

QML stellt im Rahmen der integrierten QML-Typen mehrere Arten von Datenmodellen bereit. Darüber hinaus können Modelle mit Qt C++ erstellt und anschließend „ QQmlEngine “ zur Verwendung durch QML-Komponenten zur Verfügung gestellt werden. Informationen zum Erstellen dieser Modelle finden Sie in den Artikeln „Verwendung von C++-Modellen mit Qt Quick -Ansichten “ und „Erstellen von QML-Typen “.

Die Positionierung von Elementen aus einem Modell kann mithilfe eines „ Repeater “ erfolgen.

Listenmodell

ListModel ist eine einfache Hierarchie von Typen, die in QML definiert sind. Die verfügbaren Rollen werden durch die Eigenschaften des „ ListElement “ festgelegt.

ListModel {
    id: fruitModel

    ListElement {
        name: "Apple"
        cost: 2.45
    }
    ListElement {
        name: "Orange"
        cost: 3.25
    }
    ListElement {
        name: "Banana"
        cost: 1.95
    }
}

Das obige Modell verfügt über zwei Rollen: „name “ und „cost“. Diese können über einen „ ListView “-Delegaten gebunden werden, zum Beispiel:

ListView {
    anchors.fill: parent
    model: fruitModel
    delegate: Row {
        id: delegate
        required property string name
        required property real cost

        Text { text: "Fruit: " + delegate.name }
        Text { text: "Cost: $" + delegate.cost }
    }
}

ListModel bietet Methoden zur direkten Bearbeitung des „ ListModel “ über JavaScript. In diesem Fall bestimmt das erste eingefügte Element die Rollen, die für alle Ansichten verfügbar sind, die das Modell verwenden. Wenn beispielsweise ein leeres „ ListModel “ erstellt und über JavaScript gefüllt wird, sind die durch die erste Einfügung bereitgestellten Rollen die einzigen, die in der Ansicht angezeigt werden:

ListModel { id: fruitModel }
    ...
MouseArea {
    anchors.fill: parent
    onClicked: fruitModel.append({"cost": 5.95, "name":"Pizza"})
}

Wenn auf „ MouseArea “ geklickt wird, verfügt „ fruitModel “ über zwei Rollen: „cost“ und „name“. Selbst wenn später weitere Rollen hinzugefügt werden, werden von den Ansichten, die das Modell verwenden, nur die ersten beiden berücksichtigt. Um die im Modell verfügbaren Rollen zurückzusetzen, rufen Sie „ ListModel::clear()“ auf.

XML-Modell

XmlListModel ermöglicht die Erstellung eines Modells aus einer XML-Datenquelle. Die Rollen werden über den Typ „ XmlListModelRole “ festgelegt. Der Typ muss importiert werden.

import QtQml.XmlListModel

Das folgende Modell verfügt über drei Rollen: „title“, „link“ und „pubDate“:

XmlListModel {
     id: feedModel
     source: "http://rss.news.yahoo.com/rss/oceania"
     query: "/rss/channel/item"
     XmlListModelRole { name: "title"; elementName: "title" }
     XmlListModelRole { name: "link"; elementName: "link" }
     XmlListModelRole { name: "pubDate"; elementName: "pubDate" }
}

Die Eigenschaft „ query “ legt fest, dass der „ XmlListModel “ für jeden „ <item> “ im XML-Dokument ein Modellelement generiert.

Die RSS-News-Demo zeigt, wie „ XmlListModel “ zur Anzeige eines RSS-Feeds verwendet werden kann.

Objektmodell

ObjectModel enthält die visuellen Elemente, die in einer Ansicht verwendet werden sollen. Wenn ein „ ObjectModel “ in einer Ansicht verwendet wird, benötigt die Ansicht keinen Delegaten, da der „ ObjectModel “ bereits den visuellen Delegaten (Elemente) enthält.

Im folgenden Beispiel werden drei farbige Rechtecke in einem „ ListView “ platziert.

import QtQuick 2.0
import QtQml.Models 2.1

Rectangle {
    ObjectModel {
        id: itemModel
        Rectangle { height: 30; width: 80; color: "red" }
        Rectangle { height: 30; width: 80; color: "green" }
        Rectangle { height: 30; width: 80; color: "blue" }
    }

    ListView {
        anchors.fill: parent
        model: itemModel
    }
}

Ganzzahlen als Modelle

Eine ganze Zahl kann als Modell verwendet werden, das eine bestimmte Anzahl von Typen enthält. In diesem Fall weist das Modell keine Datenrollen auf.

Im folgenden Beispiel wird ein „ ListView “ mit fünf Elementen erstellt:

Item {
    width: 200; height: 250

    Component {
        id: itemDelegate

        Text {
            required property int index
            text: "I am item number: " + index
        }
    }

    ListView {
        anchors.fill: parent
        model: 5
        delegate: itemDelegate
    }

}

Hinweis: Die Anzahl der Elemente in einem ganzzahligen Modell ist auf 100.000.000begrenzt .

Objektinstanzen als Modelle

Eine Objektinstanz kann verwendet werden, um ein Modell mit einem einzigen Objekttyp zu definieren. Die Eigenschaften des Objekts werden als Rollen bereitgestellt.

Das folgende Beispiel erstellt eine Liste mit einem Element, das die Farbe des Texts „myText“ anzeigt. Beachten Sie die Verwendung der vollständig qualifizierten Eigenschaft „model.color“, um Konflikte mit der Eigenschaft „color“ des Typs „Text“ im Delegaten zu vermeiden.

Rectangle {
    width: 200; height: 250

    Text {
        id: myText
        text: "Hello"
        color: "#dd44ee"
    }

    Component {
        id: myDelegate

        Text {
            required property var model
            text: model.color
        }
    }

    ListView {
        anchors.fill: parent
        anchors.topMargin: 30
        model: myText
        delegate: myDelegate
    }
}

C++-Datenmodelle

Modelle können in C++ definiert und anschließend für QML verfügbar gemacht werden. Dieser Mechanismus ist nützlich, um bestehende C++-Datenmodelle oder anderweitig komplexe Datensätze für QML zugänglich zu machen.

Weitere Informationen finden Sie im Artikel „Verwendung von C++-Modellen mit Qt Quick -Ansichten “.

Array-Modelle

Sie können JavaScript-Arrays und verschiedene Arten von QML-Listen als Modelle verwenden. Die Elemente der Liste werden gemäß den oben beschriebenen Regeln als „model“ und „modelData“ bereitgestellt: Einzelne Daten wie Ganzzahlen oder Zeichenketten werden als einzelnes „modelData“ bereitgestellt. Strukturierte Daten wie JavaScript-Objekte oder QObjects werden als strukturiertes „model“ und „modelData“ bereitgestellt.

Die einzelnen Modellrollen werden ebenfalls bereitgestellt, wenn Sie sie als erforderliche Eigenschaften anfordern. Da wir im Voraus nicht wissen können, welche Objekte in einem Array vorkommen, wird jede erforderliche Eigenschaft in einem Delegaten gefüllt, möglicherweise mit einer Typumwandlung von „ undefined “ in den erforderlichen Typ. Die einzelnen Modellrollen werden jedoch nicht über den QML-Kontext bereitgestellt. Sie würden alle anderen Kontexteigenschaften überschreiben.

Repeater

Texteinträge „Ich bin Eintrag 0“ bis „Ich bin Eintrag 9“

Repeater erstellen Elemente aus einer Vorlage zur Verwendung mit Positionern, wobei sie Daten aus einem Modell nutzen. Die Kombination von Repeatern und Positionern ist eine einfache Möglichkeit, viele Elemente anzuordnen. Ein „ Repeater “-Element wird in einen Positioner eingefügt und generiert Elemente, die der umschließende Positioner anordnet.

Jeder Repeater erstellt eine bestimmte Anzahl von Elementen, indem er jedes Datenelement aus einem Modell – das über die Eigenschaft „ model “ angegeben wird – mit dem Vorlagenelement kombiniert, das als untergeordnetes Element innerhalb des Repeaters definiert ist. Die Gesamtzahl der Elemente richtet sich nach der Datenmenge im Modell.

Das folgende Beispiel zeigt einen Repeater, der zusammen mit einem „Grid“-Element verwendet wird, um eine Reihe von „Rectangle“-Elementen anzuordnen. Das Repeater-Element erzeugt eine Reihe von 24 Rechtecken, die das „Grid“-Element in einer 5×5-Anordnung positioniert.

import QtQuick

Rectangle {
    width: 400
    height: 400
    color: "black"

    Grid {
        x: 5
        y: 5
        rows: 5
        columns: 5
        spacing: 10

        Repeater {
            model: 24
            Rectangle {
                id: delegate

                required property int index

                width: 70
                height: 70
                color: "lightgreen"

                Text {
                    text: delegate.index
                    font.pointSize: 30
                    anchors.centerIn: parent
                }
            }
        }
    }
}

Die Anzahl der von einem „Repeater“ erstellten Elemente wird durch dessen Eigenschaft „ count “ gespeichert. Es ist nicht möglich, diese Eigenschaft so festzulegen, dass die Anzahl der zu erstellenden Elemente bestimmt wird. Stattdessen verwenden wir, wie im obigen Beispiel, eine Ganzzahl als Modell.

Weitere Informationen finden Sie im Dokument „QML-Datenmodelle “.

Wenn es sich bei dem Modell um eine Zeichenfolgenliste handelt, steht dem Delegaten außerdem die übliche schreibgeschützte Eigenschaft „ modelData “ zur Verfügung, die die Zeichenfolge enthält. Beispiel:

Column {
    Repeater {
        model: ["apples", "oranges", "pears"]
        Text {
            required property string modelData
            text: "Data: " + modelData
        }
    }
}

Text mit den Daten: Äpfel, Daten: Orangen, Daten: Birnen

Es ist auch möglich, einen Delegaten als Vorlage für die von einem „Repeater“ erstellten Elemente zu verwenden. Dies wird über die Eigenschaft „ delegate “ festgelegt.

Ändern von Modelldaten

Alle relevanten Ansichten verfügen über eine Eigenschaft namens „delegateModelAccess“, die festlegt, ob und wie Sie Modelldaten über den Delegaten ändern können. In den meisten Anwendungsfällen sollten Sie diese Eigenschaft auf „DelegateModel.ReadWrite“ setzen. Dadurch kann Ihr Delegat Modelldaten auf die flexibelste Weise ändern. Alternativ können Sie sie auf „DelegateModel.ReadOnly“ setzen, wenn Sie nicht möchten, dass der Delegat Modelldaten überhaupt ändert.

Die folgende Tabelle beschreibt detailliert alle Werte, die die Eigenschaft annehmen kann.

DelegateModel.Qt5ReadWriteDer Delegat kann allen von der Ansicht bereitgestellten Kontexteigenschaften Werte zuweisen, um das entsprechende Modellelement zu ändern. Darüber hinaus kann er auch Eigenschaften des Objekts ` model `, die entweder als Kontexteigenschaft oder als erforderliche Eigenschaft bereitgestellt werden, mit demselben Effekt Werte zuweisen. Der Delegat kann jedoch keine Modelldaten ändern, indem er Werten an erforderliche Eigenschaften zuweist, die von der Ansicht gefüllt werden. Wenn Sie einer erforderlichen Eigenschaft eines Delegaten einen Wert zuweisen, wird die Bindung unterbrochen, die die erforderliche Eigenschaft anhand der Modelldaten aktualisiert. Dadurch behält die erforderliche Eigenschaft den von Ihnen zugewiesenen Wert bei, selbst wenn sich das Modell später ändert. DelegateModel.Qt5ReadWrite ist der Standardwert von delegateModelAccess.
DelegateModel.ReadOnlyDer Delegat kann weder Werte an von der Ansicht bereitgestellte Kontext-Eigenschaften noch an Eigenschaften des Objekts „ model “ zuweisen. Das Zuweisen eines Werts an eine von der Ansicht gefüllte erforderliche Eigenschaft unterbricht weder die interne Bindung noch verändert es Modelldaten. Die erforderliche Eigenschaft behält den ihr zugewiesenen Wert bei, bis sich das Modellelement erneut ändert.
DelegateModel.ReadWriteDer Delegat kann allen von der Ansicht bereitgestellten Kontexteigenschaften Werte zuweisen, um das entsprechende Modellelement zu ändern. Darüber hinaus kann er auch Eigenschaften des „ model “-Objekts, die entweder als Kontexteigenschaft oder als erforderliche Eigenschaft bereitgestellt werden, mit demselben Effekt Werte zuweisen. Der Delegat kann Modelldaten auch ändern, indem er Werte den von der Ansicht gefüllten erforderlichen Eigenschaften zuweist. Die Zuweisung eines Werts zu einer erforderlichen Eigenschaft leitet den Wert an das jeweilige Modellelement weiter, ohne interne Bindungen zu unterbrechen.

Einige Modelle sind Objekte mit eigenständigen Identitäten, auf die die Ansicht verweist. Das ursprüngliche Objekt ist die einzige Quelle der Wahrheit für die Erstellung von Delegaten. Es wird nicht kopiert. Solche Modelle werden beim Schreiben über Delegaten sichtbar aktualisiert.

Andere Modelle verfügen über keine eigenständige Identität und werden bei der Zuweisung an die Ansicht kopiert. Bei solchen Modellen werden beim Schreiben über den Delegaten lediglich die internen Strukturen der Ansicht aktualisiert. Das ursprüngliche Modell bleibt unverändert.

Im Allgemeinen verfügen QML-Objekttypen über eigenständige Identitäten, QML-Werttypen hingegen nicht. ListModel, alles, was von ` QAbstractItemModel` abgeleitet ist, sowie entweder eine einzelne Instanz eines Objekttyps oder eine Liste von Instanzen von Objekttypen werden also aktualisiert, wenn sie als Modell übergeben und über den Delegaten geschrieben werden. JavaScript-Arrays, Listen von Werttypen oder einfache Zahlen werden jedoch nicht aktualisiert, wenn Sie Modelldaten über den Delegaten ändern.

Darüber hinaus müssen Sie bei der Implementierung Ihres eigenen C++-Modells die Methode ` setData ` implementieren, um von Delegaten übergebene Aktualisierungen zu empfangen.

Angenommen, ein auf „ QAbstractItemModel “ basierendes C++-Modell, das die Methode „ setData “ implementiert, ist als QML-Typ mit dem Namen „ EditableModel “ registriert. Daten könnten dann wie folgt in das Modell geschrieben werden:

ListView {
    anchors.fill: parent
    model: EditableModel {}

    // Make sure that changes to the required property are propagated
    delegateModelAccess: DelegateModel.ReadWrite

    delegate: TextEdit {
        required property string edit

        width: ListView.view.width
        height: 30
        text: edit
        Keys.onReturnPressed: edit = text
    }
}

Sie können Modelldaten auch ändern, indem Sie das ` model `-Objekt wie folgt bearbeiten:

ListView {
    anchors.fill: parent
    model: EditableModel {}
    delegate: TextEdit {
        required property QtObject model

        width: ListView.view.width
        height: 30
        text: model.edit
        Keys.onReturnPressed: model.edit = text
    }
}

Hinweis: Die Rolle „ edit “ entspricht „ Qt::EditRole “. Eine Übersicht über die integrierten Rollennamen finden Sie unter roleNames(). In der Praxis werden in Modellen jedoch in der Regel benutzerdefinierte Rollen registriert.

Weitere Informationen finden Sie im Artikel „Verwenden von C++-Modellen mit Qt Quick -Ansichten “.

Verwendung von Übergängen

Übergänge können verwendet werden, um Elemente zu animieren, die zu einem Positionierer hinzugefügt, innerhalb dieses verschoben oder aus diesem entfernt werden.

Übergänge zum Hinzufügen von Elementen gelten sowohl für Elemente, die als Teil eines Positioners erstellt werden, als auch für solche, die neu zugeordnet werden, um zu untergeordneten Elementen eines Positioners zu werden.

Übergänge beim Entfernen von Elementen gelten sowohl für Elemente innerhalb eines Positionierers, die gelöscht werden, als auch für solche, die aus einem Positionierer entfernt und im Dokument neuen übergeordneten Elementen zugeordnet werden.

Hinweis: Das Setzen der Deckkraft von Elementen auf Null führt nicht dazu, dass sie aus dem Positionierer verschwinden. Sie können entfernt und erneut hinzugefügt werden, indem die Eigenschaft „visible“ geändert wird.

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.