web-dev-qa-db-fra.com

Différents délégués pour QML ListView

J'aimerais savoir s'il est possible d'utiliser (plusieurs) délégués différents pour un QML ListView

En fonction de l'objet individuel dans le modèle ListView, j'aimerais visualiser les objets avec différents délégués.

Ce morceau de code explique ce que je veux réaliser: 

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 (Un composant possible que j'aimerais utiliser en tant que délégué)

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 (autre composant que je voudrais utiliser en tant que délégué)

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
    }
}

J'apprécierais n'importe quel conseil! Merci!

16
dh1tw

Je pense qu'il serait préférable d'implémenter un délégué de base pour tout type de position qui charge une implémentation concrète en fonction de position ou de toute autre propriété de données utilisant Loader

BaseDelegate {
    property var position

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

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

J'ai eu le même problème, la documentation Qt fournit une très bonne réponse: http://doc.qt.io/qt-5/qml-qtquick-loader.html#using-a-loader-within- a-view-delegate

La solution la plus simple est une Component en ligne avec une Loader pour définir un fichier source:

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"
            }
        }
    }
}

Toute tentative d'utilisation de Loader.srcComponent entraînera la perte de toute variable du modèle (y compris index). La seule manière pour que les variables soient présentes est que les enfants Component soient à l'intérieur de la Component principale, mais un seul peut être présent, donc c'est inutile.

10
Aurélien Lambert

Je l'ai implémenté comme suit:

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 { /*....*/ }
}

Dernière note, vérifiez la largeur et la hauteur des délégués. Dans mon cas, je devais régler la largeur et la hauteur de mon délégué dans Loader.
Bonne chance - Mousavi

5
S.M.Mousavi

Dans la mesure où vous n’avez que deux types, le code suivant est aussi facile à gérer qu’à comprendre:

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

Au cas où le nombre de types augmenterait, ce n'est pas une solution appropriée car cela mène facilement à une déclaration if si difficile.

0
skypjack