web-dev-qa-db-de.com

Verschiedene Delegaten für QML ListView

Ich würde gerne wissen, ob es möglich ist, verschiedene Delegaten für eine QML ListView zu verwenden. 

Abhängig vom einzelnen Objekt im Modell ListView möchte ich die Objekte mit unterschiedlichen Delegierten visualisieren.

Dieser Code erklärt, was ich erreichen möchte: 

main.qml

import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2

ApplicationWindow {
    title: qsTr("Hello World")
    width: 640
    height: 480
    visible: true

    ListModel {
        id: contactsModel
        ListElement {
            name: "Bill Smith"
            position: "Engineer"
        }
        ListElement {
            name: "John Brown"
            position: "Engineer"
        }
        ListElement {
            name: "Sam Wise"
            position: "Manager"
        }
    }

    ListView {
        id: contactsView
        anchors.left: parent.left
        anchors.top: parent.top
        width: parent.width
        height: parent.height
        orientation: Qt.Vertical
        spacing: 10
        model: contactsModel
        delegate: {
            if (position == "Engineer") return Employee;  //<--- depending on condition, load Contact{}
            else if (position == "Manager") return Manager; //<--- depending on condition, load Person{}
        }
    }
}

Employee.qml (Eine mögliche Komponente, die ich als Delegierter verwenden möchte)

import QtQuick 2.4

Rectangle{
    width: 200
    height: 50
    color: ListView.isCurrentItem ? "#003366" : "#585858"
    border.color: "gray"
    border.width: 1

    Text{
        anchors.centerIn: parent
        color: "white"
        text: name
    }
}

Manager.qml (andere Komponente, die ich als Delegierter verwenden möchte)

import QtQuick 2.4

Rectangle{
    width: 200
    height: 50
    color: "red"
    border.color: "blue"
    border.width: 1

    Text{
        anchors.centerIn: parent
        color: "white"
        text: name
    }
}

Ich würde mich über einen Rat freuen! Danke!

16
dh1tw

Ich glaube, es wäre besser, einen Basisdelegierten für alle Arten von position zu implementieren, der die konkrete Implementierung abhängig von position oder anderen Dateneigenschaften mit Loader lädt

BaseDelegate {
    property var position

    Loader {
        sourceComponent: {
            switch(position) {
                case "Engineer": return engineerDelegate
            }
        }
    }

    Component {
        id: engineerDelegate
        Rectangle {
             Text {  }
        }
    }
}
11
Andrii

Ich hatte das gleiche Problem, die Qt-Dokumentation liefert eine ziemlich gute Antwort: http://doc.qt.io/qt-5/qml-qtquick-loader.html#using-a-loader-within- a-view-delegate

Die einfachste Lösung ist eine Inline Component mit einer Loader, um eine source-Datei festzulegen:

ListView {
    id: contactsView
    anchors.left: parent.left
    anchors.top: parent.top
    width: parent.width
    height: parent.height
    orientation: Qt.Vertical
    spacing: 10
    model: contactsModel
    delegate: Component {
        Loader {
            source: switch(position) {
                case "Engineer": return "Employee.qml"
                case "Manager": return "Manager.qml"
            }
        }
    }
}

Bei jedem Versuch, Loader.srcComponent zu verwenden, werden alle Variablen aus dem Modell (einschließlich index) ausgelassen. Die Variablen können nur vorhanden sein, wenn sich die Kinder Component im Haupt Component befinden, aber dann kann nur eine vorhanden sein, also ist sie unbrauchbar.

10

Ich habe es wie folgt umgesetzt:

ListView {
    id: iranCitiesList
    model: sampleModel
    delegate: Loader {
        height: childrenRect.height
        width: parent.width
        sourceComponent: {
            switch(itemType) {
            case "image" :
                return imageDel;
            case "video":
                return videoDel;
            }
        }
    }
    ImageDelegate { id: imageDel }
    VideoDelegate { id: videoDel }
}


ImageDelegate.qml

Component {
    Image { /*...*/ }
}


VideoDelegate.qml

Component {
    Item { /*....*/ }
}

Letzte Notiz, überprüfen Sie die Breite und Höhe der Delegierten. In meinem Fall musste ich Breite und Höhe meines Delegierten erneut in Loader einstellen.
Viel Glück - Mousavi

5
S.M.Mousavi

Soweit Sie nur zwei Typen haben, ist der folgende Code so einfach zu pflegen wie einfach zu verstehen:

delegate: Item {
    Employee { visible = position === "Engineer" }
    Manager { visible = position === "Manager" }
}

Für den Fall, dass die Anzahl der Typen zunimmt, ist dies keine geeignete Lösung, da dies leicht zu einer verdammten if-Anweisung führt.

0
skypjack