Different delegates for QML ListView

前端 未结 6 841
自闭症患者
自闭症患者 2020-12-13 19:36

I would like to know if it\'s possible to use (several) different delegates for a QML ListView.

Depending on the individual object in the ListVie

相关标签:
6条回答
  • 2020-12-13 19:57

    The simplest way to do this now is using DelegateChooser. This also allows you to edit the properties of the delegates, which is something that is more difficult to do with Loader!

    Example inspired from the docs:

    import QtQuick 2.14
    import QtQuick.Controls 2.14
    import Qt.labs.qmlmodels 1.0
    
    ListView {
        width: 640; height: 480
    
        ListModel {
            id: contactsModel
        ListElement {
            name: "Bill Smith"
            position: "Engineer"
        }
        ListElement {
            name: "John Brown"
            position: "Engineer"
        }
        ListElement {
            name: "Sam Wise"
            position: "Manager"
        }
       }
    
        DelegateChooser {
            id: chooser
            role: "position"
            DelegateChoice { roleValue: "Manager"; Manager { ... } }
            DelegateChoice { roleValue: "Employee"; Employee { ... } }
        }
    
        model: contractsModel
        delegate: chooser
    }
    
    0 讨论(0)
  • 2020-12-13 19:58

    I believe it would be better to implement one base delegate for all kind of position which loads concrete implementation depending on position or any other data properties using Loader

    BaseDelegate {
        property var position
    
        Loader {
            sourceComponent: {
                switch(position) {
                    case "Engineer": return engineerDelegate
                }
            }
        }
    
        Component {
            id: engineerDelegate
            Rectangle {
                 Text {  }
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-13 19:59

    As far as you have only two types, the following code is as easy to maintain as easy to understand:

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

    In case the number of types will grow, it is not a suitable solution for it easily leads to an hell of if statement.

    0 讨论(0)
  • 2020-12-13 20:12

    I've had the same problem, the Qt documentation is providing a pretty good answer: http://doc.qt.io/qt-5/qml-qtquick-loader.html#using-a-loader-within-a-view-delegate

    The easiest solution is an inline Component with a Loader to set a source file:

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

    Any attempt to use Loader.srcComponent will result in missing any variable from the model (including index). The only way for the variables to be present is the children Component to be inside the main Component, but then only one can be present, so it is useless.

    0 讨论(0)
  • 2020-12-13 20:12

    I implemented it as follow:

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

    Last note, check width and height of delegates. In my case, I had to set width and height of my delegate in Loader again.
    Good luck - Mousavi

    0 讨论(0)
  • 2020-12-13 20:18

    Sure, it's possible. ListView.delegate is a kind of pointer to a Component which will draw the items so you can change it.

    For example:

    Employee { id: delegateEmployee }
    Manager { id: delegateManager}
    ...
    ListView {  
        property string position   
        delegate: position == "Engineer" ? delegateEmployee : delegateManager
    }
    
    0 讨论(0)
提交回复
热议问题