Modelle und Ansichten in Qt Quick

Die meisten Anwendungen müssen Daten formatieren und anzeigen. Qt Quick hat den Begriff der Modelle, Ansichten und Delegierten zur Anzeige von Daten. Sie modularisieren die Visualisierung von Daten, um dem Entwickler oder Designer die Kontrolle über die verschiedenen Aspekte der Daten zu geben. Ein Entwickler kann eine Listenansicht mit einer Rasteransicht austauschen, ohne dass sich an den Daten etwas ändert. In ähnlicher Weise kann der Entwickler durch die Kapselung einer Dateninstanz in einem Delegaten bestimmen, wie die Daten dargestellt oder verarbeitet werden sollen.

  • Modell - enthält die Daten und ihre Struktur. Es gibt mehrere QML-Typen zur Erstellung von Modellen.
  • View - ein Container, der die Daten anzeigt. Die Ansicht kann die Daten in einer Liste oder einem Gitter darstellen.
  • Delegate - legt fest, wie die Daten in der Ansicht angezeigt werden sollen. Der Delegat nimmt jede Dateneinheit im Modell und kapselt sie ein. Der Zugriff auf die Daten erfolgt über den Delegaten. Der Delegat kann auch Daten in bearbeitbare Modelle zurückschreiben (z.B. in einem TextField's onAccepted Handler).

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.

Anzeige von Daten mit Views

Ansichten sind Container für Sammlungen von Elementen. Sie verfügen über eine Vielzahl von Funktionen und können angepasst werden, um Stil- oder Verhaltensanforderungen zu erfüllen.

Eine Reihe von Standardansichten sind im Basissatz der grafischen Typen von Qt Quick enthalten:

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

Darüber hinaus Qt Quick Controls einige zusätzliche Ansichten und Delegaten, die entsprechend dem Anwendungsstil gestylt sind, zum Beispiel HorizontalHeaderView und VerticalHeaderView.

Ausschmücken von Ansichten

Ansichten ermöglichen die visuelle Anpassung durch Dekorationseigenschaften wie die Eigenschaften header, footer und section. Durch die Bindung eines Objekts, in der Regel eines anderen visuellen Objekts, an diese Eigenschaften sind die Ansichten dekorierbar. Eine Fußzeile kann einen Rectangle Typ enthalten, der Ränder oder eine Kopfzeile zeigt, die ein Logo über der Liste anzeigt.

Nehmen wir an, dass ein bestimmter Verein seine Mitgliederliste mit seinen Markenfarben schmücken möchte. Eine Mitgliederliste befindet sich in einer model und die 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
    }
}

Der Verein kann die Mitgliederliste dekorieren, indem er visuelle Objekte an die Eigenschaften header und footer bindet. Das visuelle Objekt kann inline, in einer anderen Datei oder in einem Component Typ 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 {
        width: parent.width
        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"}
}

Handhabung von Maus und Berührung

Die Ansichten verarbeiten das Ziehen und Streichen ihres Inhalts, jedoch nicht die Berührungsinteraktion mit den einzelnen Delegaten. Damit die Delegaten auf Berührungseingaben reagieren können, z. B. um die currentIndex einzustellen, muss ein MouseArea mit der entsprechenden Logik für die Berührungsbehandlung vom Delegaten bereitgestellt werden.

Beachten Sie, dass, wenn highlightRangeMode auf StrictlyEnforceRange gesetzt ist, der currentIndex durch Ziehen/Bewegen der Ansicht beeinflusst wird, da die Ansicht immer sicherstellt, dass currentIndex innerhalb des angegebenen Markierungsbereichs liegt.

ListView-Abschnitte

ListView Inhalte können in Abschnitte gruppiert werden, wobei zusammengehörige Listenelemente entsprechend ihrer Abschnitte beschriftet werden. Außerdem können die Abschnitte mit Delegaten dekoriert werden.

Eine Liste kann eine Liste enthalten, die die Namen von Personen und das Team, zu dem die Person gehört, angibt.

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 {
        text: name;
        font.pixelSize: 24
        anchors.left: parent.left
        anchors.leftMargin: 2
    }
}

Der Typ ListView hat die angehängte Eigenschaft section, die benachbarte und verwandte Typen zu einem Abschnitt zusammenfassen kann. Die section.property bestimmt, welche Eigenschaft des Listentyps als Abschnitt verwendet werden soll. Mit section.criteria kann festgelegt werden, wie die Abschnittsnamen angezeigt werden, und section.delegate ähnelt der Eigenschaft delegate 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
            }
        }
    }
}

Ansicht Delegaten

Ansichten benötigen einen Delegaten, um ein Element in einer Liste visuell darzustellen. Eine Ansicht stellt jedes Element in einer Liste entsprechend der vom Delegaten definierten Vorlage dar. Auf Elemente in einem Modell kann über die Eigenschaft index sowie ü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
    }
}

Positionierung von Ansichtsdelegaten

Die Art der Ansicht bestimmt, wie die Elemente positioniert werden. ListView positioniert die Elemente in einer geraden Linie, abhängig von orientation, während GridView sie in einem 2-dimensionalen Gitter anordnen kann. Es wird nicht empfohlen, direkt an x und y zu binden, da das Layoutverhalten der Ansicht immer Vorrang vor einer Positionsbindung hat.

Zugriff auf Views und Models von Delegates aus

Die Listenansicht, an die der Delegat gebunden ist, ist vom Delegaten über die Eigenschaft ListView.view zugänglich. Ebenso ist die GridView GridView.view für Delegierte verfügbar. Das entsprechende Modell und seine Eigenschaften sind daher über ListView.view.model verfügbar. Darüber hinaus sind alle definierten Signale oder Methoden im Modell ebenfalls zugänglich.

Dieser Mechanismus ist nützlich, wenn Sie z. B. denselben Delegierten für eine Reihe von Ansichten verwenden möchten, aber die Dekorationen oder andere Funktionen für jede Ansicht unterschiedlich sein sollen, und Sie möchten, dass diese unterschiedlichen Einstellungen Eigenschaften der einzelnen Ansichten sind. In ähnlicher Weise kann es von Interesse sein, auf einige 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
                Text { text: " Fruit: " + name; color: fruit.ListView.view.fruit_color }
                Text { text: " Cost: $" + 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 zur Verfügung gestellt, an die der Delegat binden kann. Hier ist eine ListModel mit zwei Rollen, Typ und Alter, und eine ListView mit einem Delegaten, der sich an diese Rollen bindet, um ihre 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 erforderliche Eigenschaften verwenden, um Modelldaten an Ihre Delegaten zu übergeben. Wenn ein Delegat erforderliche Eigenschaften enthält, prüft die QML-Engine, ob der Name einer erforderlichen Eigenschaft mit dem einer Modellrolle übereinstimmt. Wenn dies der Fall ist, wird diese Eigenschaft an den entsprechenden Wert des Modells gebunden.

In seltenen Eckfällen können Sie die Modelleigenschaften über den QML-Kontext und nicht als erforderliche Eigenschaften übertragen wollen. Wenn keine erforderlichen Eigenschaften in Ihrem Delegaten vorhanden sind, werden die genannten 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
    }
}

Kontexteigenschaften sind für das Tooling unsichtbar und verhindern, dass das Qt Quick Compiler daran, Ihren Code zu optimieren. Sie machen es schwieriger, über die spezifischen Daten, die Ihr Delegat erwartet, nachzudenken. Es gibt keine Möglichkeit, den QML-Kontext explizit von QML aus zu befüllen. Wenn Ihre Komponente erwartet, dass Daten über den QML-Kontext übergeben werden, können Sie sie nur dort verwenden, wo der richtige Kontext auf nativem Wege zur Verfügung gestellt wird. Dies kann Ihr eigener C++-Code oder die spezifischen Implementierungen der umgebenden Elemente sein. Umgekehrt können erforderliche Eigenschaften auf verschiedene Weise von QML aus oder mit nativen Mitteln 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 auf die Rollen stattdessen mit dem qualifizierten Modellnamen zugegriffen werden. Wenn beispielsweise ein Typ Text über (nicht erforderliche) Typ- oder Alterseigenschaften verfügt, würde der Text im obigen Beispiel diese Eigenschaftswerte anstelle der Typ- und Alterswerte aus dem Modellelement anzeigen. In diesem Fall könnten die Eigenschaften stattdessen als model.type und model.age referenziert werden, um sicherzustellen, dass der Delegierte die Eigenschaftswerte aus dem Modellelement anzeigt. Damit dies funktioniert, müssen Sie eine model Eigenschaft in Ihrem Delegaten benötigen (außer Sie verwenden Kontexteigenschaften).

Eine spezielle Indexrolle, die den Index des Elements im Modell enthält, ist auch für den Delegaten verfügbar. Beachten Sie, dass dieser Index auf -1 gesetzt wird, wenn das Element aus dem Modell entfernt wird. Wenn Sie an die Indexrolle binden, 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 werden, aber es ist möglich, die Zerstörung in einigen Ansichten über eine delayRemove angehängte Eigenschaft zu verzögern).

Denken Sie daran, dass Sie Ganzzahlen oder Arrays als Modell 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 ein einzelnes, anonymes Stück Daten zur Verfügung. Der Zugriff auf dieses Datenelement ist der Hauptgrund für die Verwendung von modelData, aber auch andere Modelle bieten modelData.

Das Objekt, das über die Modellrolle bereitgestellt wird, hat eine Eigenschaft mit einem leeren Namen. Diese anonyme Eigenschaft enthält die modelData. Außerdem verfügt das über die Modellrolle 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 Rolle modelData enthält die gleichen Daten wie die Eigenschaft modelData und die anonyme Eigenschaft des über die Rolle model bereitgestellten Objekts.

Die Unterschiede zwischen der model-Rolle und den verschiedenen Möglichkeiten des Zugriffs auf modelData sind die folgenden:

  • Bei Modellen, die keine benannten Rollen haben (z. B. Ganzzahlen oder ein Array von Strings), werden die Daten über die modelData-Rolle bereitgestellt. Die modelData-Rolle enthält in diesem Fall nicht unbedingt ein Objekt. Im Falle eines Integer-Modells würde sie eine ganze Zahl enthalten (den Index des aktuellen Modellelements). Im Falle eines Arrays von Strings würde sie einen String enthalten. Die Modellrolle enthält immer noch ein Objekt, aber ohne Eigenschaften für benannte Rollen. model enthält aber immer noch seine üblichen modelData und anonymen Eigenschaften.
  • Wenn das Modell nur eine benannte Rolle hat, enthält die modelData-Rolle die gleichen Daten wie die benannte Rolle. Sie ist nicht notwendigerweise ein Objekt und enthält die benannte Rolle nicht als benannte Eigenschaft, wie es normalerweise der Fall wäre. Die Modellrolle enthält nach wie vor ein Objekt mit der benannten Rolle als Eigenschaft, und in diesem Fall die Eigenschaften modelData und anonymous.
  • Bei Modellen mit mehreren Rollen wird die modelData-Rolle nur als erforderliche Eigenschaft bereitgestellt, nicht als Kontexteigenschaft. Dies geschieht aus Gründen der Abwärtskompatibilität mit älteren Versionen von Qt.

Die anonyme Eigenschaft auf model ermöglicht es Ihnen, Delegates 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 einem leeren String als Rolle bereitstellen. Dann wird eine Bindung, die einfach auf model[role] zugreift, das tun, 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 hat auch erforderliche Eigenschaften mit passenden Namen.

QML bietet mehrere Typen von Datenmodellen aus dem eingebauten Satz von QML-Typen. Darüber hinaus können Modelle mit Qt C++ erstellt und dann QQmlEngine zur Verwendung durch QML-Komponenten zur Verfügung gestellt werden. Informationen zum Erstellen dieser Modelle finden Sie in den Artikeln Verwenden von C++-Modellen mit Qt Quick Views und Erstellen von QML-Typen.

Die Positionierung von Elementen aus einem Modell kann mit einem Repeater erreicht werden.

Listenmodell

ListModel ist eine einfache Hierarchie von in QML spezifizierten Typen. Die verfügbaren Rollen werden durch die ListElement Eigenschaften spezifiziert.

ListModel {
    id: fruitModel

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

Das obige Modell hat zwei Rollen, name und cost. Diese können z. B. durch einen ListView Delegaten gebunden werden:

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, um die ListModel direkt über JavaScript zu manipulieren. In diesem Fall bestimmt das erste eingefügte Element die verfügbaren Rollen für alle Ansichten, die das Modell verwenden. Wenn zum Beispiel ein leeres ListModel erstellt und über JavaScript gefüllt wird, sind die Rollen, die durch das erste Einfügen bereitgestellt werden, die einzigen Rollen, die in der Ansicht angezeigt werden:

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

Wenn MouseArea angeklickt wird, hat fruitModel zwei Rollen, Kosten und Name. Auch wenn weitere Rollen hinzugefügt werden, werden nur die ersten beiden von den Ansichten, die das Modell verwenden, verarbeitet. Um die im Modell verfügbaren Rollen zurückzusetzen, rufen Sie ListModel::clear() auf.

XML-Modell

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

import QtQml.XmlListModel

Das folgende Modell hat 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 gibt an, dass XmlListModel für jedes <item> im XML-Dokument ein Modellelement erzeugt.

Die RSS-News-Demo zeigt, wie XmlListModel verwendet werden kann, um einen RSS-Feed anzuzeigen.

Objektmodell

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

Das folgende Beispiel platziert drei farbige Rechtecke in einer ListView.

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 hat das Modell keine Datenrollen.

Das folgende Beispiel erstellt eine ListView mit fünf Elementen:

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 Integer-Modell ist auf 100.000.000 begrenzt.

Objektinstanzen als Modelle

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

Im folgenden Beispiel wird eine Liste mit einem Element erstellt, das die Farbe des Textes myText anzeigt. Beachten Sie die Verwendung der vollständig qualifizierten Eigenschaft model.color, um einen Konflikt 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 werden und dann für QML verfügbar gemacht werden. Dieser Mechanismus ist nützlich, um bestehende C++-Datenmodelle oder andere komplexe Datensätze für QML verfügbar zu machen.

Weitere Informationen finden Sie im Artikel Verwenden 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 als Model und ModelData nach den oben beschriebenen Regeln zur Verfügung gestellt: Singuläre Daten wie Ganzzahlen oder Strings werden als singuläre modelData zur Verfügung gestellt. Strukturierte Daten wie JavaScript-Objekte oder QObjects werden als strukturierte model- und modelData zur Verfügung gestellt.

Die einzelnen Modellrollen werden ebenfalls zur Verfügung gestellt, wenn Sie sie als erforderliche Eigenschaften anfordern. Da wir nicht im Voraus wissen können, welche Objekte in einem Array erscheinen werden, wird jede erforderliche Eigenschaft in einem Delegaten aufgefüllt, möglicherweise mit einer Zwangsumwandlung von undefined in den erforderlichen Typ. Die einzelnen Modellrollen werden jedoch nicht über den QML-Kontext verfügbar gemacht. Sie würden alle anderen Kontexteigenschaften überschatten.

Wiederholer

Repeater erstellen Elemente aus einer Vorlage zur Verwendung mit Positionierern unter Verwendung von Daten aus einem Modell. Die Kombination von Wiederholern und Positionierern ist eine einfache Möglichkeit, viele Elemente anzuordnen. Ein Repeater Element wird innerhalb eines Positionierers platziert und erzeugt Elemente, die der umschließende Positionierer anordnet.

Jeder Repeater erzeugt eine Anzahl von Elementen, indem er jedes Datenelement aus einem Modell, das mit der Eigenschaft model angegeben wird, mit dem Vorlagenelement kombiniert, das als untergeordnetes Element innerhalb des Repeaters definiert ist. Die Gesamtzahl der Elemente wird durch die Menge der Daten im Modell bestimmt.

Das folgende Beispiel zeigt einen Repeater, der mit einem Grid-Element verwendet wird, um eine Reihe von Rectangle-Elementen anzuordnen. Das Repeater-Element erstellt eine Reihe von 24 Rechtecken, die vom Grid-Element in einer 5 x 5-Anordnung positioniert werden.

import QtQuick

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

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

        Repeater { model: 24
                   Rectangle { width: 70; height: 70
                               color: "lightgreen"

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

Die Anzahl der Elemente, die von einem Repeater erstellt werden, wird durch die Eigenschaft count festgelegt. Es ist nicht möglich, diese Eigenschaft festzulegen, um die Anzahl der zu erstellenden Elemente zu bestimmen. Stattdessen wird, wie im obigen Beispiel, eine ganze Zahl als Modell verwendet.

Weitere Einzelheiten finden Sie im Dokument QML Data Models.

Wenn das Modell eine String-Liste ist, ist der Delegat auch der üblichen schreibgeschützten Eigenschaft modelData ausgesetzt, die den String enthält. Zum Beispiel:

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

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 angegeben.

Ändern von Modelldaten

Um Modelldaten zu ändern, können Sie den model Eigenschaften aktualisierte Werte zuweisen. Die QML ListModel ist standardmäßig editierbar, während C++ Modelle setData() implementieren müssen, um editierbar zu werden. Integer- und JavaScript-Array-Modelle sind schreibgeschützt.

Angenommen, ein auf QAbstractItemModel basierendes C++-Modell, das die Methode setData implementiert, wird als QML-Typ namens EditableModel registriert. Die Daten könnten dann wie folgt in das Modell geschrieben werden:

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

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

Hinweis: Die Rolle edit ist gleich Qt::EditRole. Siehe roleNames() für die eingebauten Rollennamen. In realen Modellen werden jedoch normalerweise benutzerdefinierte Rollen registriert.

Hinweis: Wenn eine Modellrolle an eine erforderliche Eigenschaft gebunden ist, wird durch die Zuweisung dieser Eigenschaft das Modell nicht verändert. Stattdessen wird die Bindung an das Modell unterbrochen (genau wie die Zuweisung an eine andere Eigenschaft bestehende Bindungen unterbricht). Wenn Sie erforderliche Eigenschaften verwenden und die Modelldaten ändern wollen, machen Sie model auch zu einer erforderlichen Eigenschaft und weisen Sie model.propertyName zu.

Weitere Informationen finden Sie in dem Artikel Using C++ Models with Qt Quick Views.

Verwenden von Übergängen

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

Übergänge zum Hinzufügen von Elementen gelten sowohl für Elemente, die als Teil eines Positionierers erstellt werden, als auch für solche, die repariert werden, um Kinder eines Positionierers zu werden.

Übergänge zum Entfernen von Elementen gelten für Elemente innerhalb eines Positionierers, die gelöscht werden, sowie für Elemente, die aus einem Positionierer entfernt werden und neue Eltern in einem Dokument erhalten.

Hinweis: Wenn Sie die Deckkraft von Elementen auf Null setzen, verschwinden diese nicht aus dem Positionierer. Sie können entfernt und wieder hinzugefügt werden, indem Sie die Eigenschaft visible ändern.

© 2025 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.