【问题标题】:Different delegates for QML ListViewQML ListView 的不同代表
【发布时间】:2015-11-06 06:54:25
【问题描述】:

我想知道是否可以为 QML ListView 使用(多个)不同的代表。

根据ListView 模型中的单个对象,我想用不同的委托来可视化对象。

这段代码解释了我想要实现的目标:

ma​​in.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(我想用作委托的一个可能的组件)

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(我想用作委托的其他组件)

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

我将不胜感激任何建议! 谢谢!

【问题讨论】:

  • 在这种情况下,您还可以考虑创建一个唯一的delegate,它在绑定中使用position 来更改其外观。否则,您可以使用Loader,但您必须将一些信息转发给内部item,即真正的代表。 Folibis 解决方案也可以工作,但我认为在这种情况下不会,因为position 本身就是一个角色。
  • 为什么不简单地定义一个包含Rectangles 的delegate 并在每个position 基础上设置它们的visible 字段?

标签: qt listview qml qtquick2


【解决方案1】:

我也遇到了同样的问题,Qt 文档提供了一个很好的答案:http://doc.qt.io/qt-5/qml-qtquick-loader.html#using-a-loader-within-a-view-delegate

最简单的解决方案是使用Loader 内联Component 来设置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"
            }
        }
    }
}

任何使用Loader.srcComponent 的尝试都会导致模型中缺少任何变量(包括index)。变量存在的唯一方法是子 Component 位于主 Component 内,但只能存在一个,所以没用。

【讨论】:

    【解决方案2】:

    我相信最好为所有类型的position 实现一个基本委托,它根据position 或使用Loader 的任何其他数据属性加载具体实现

    BaseDelegate {
        property var position
    
        Loader {
            sourceComponent: {
                switch(position) {
                    case "Engineer": return engineerDelegate
                }
            }
        }
    
        Component {
            id: engineerDelegate
            Rectangle {
                 Text {  }
            }
        }
    }
    

    【讨论】:

    • 如果项目数量多,是否存在性能问题的风险?我知道Loaders 不是阻塞组件,但他会让很多组件在后台工作。我错了吗?
    • 这取决于委托的复杂性,而不是加载器。
    • @BaCaRoZzo 是的,我也喜欢它们,但我从来没有这样使用过它们,所以我很好奇这个解决方案是否存在性能问题。 ;-)
    • @skypjack 你看到链接的视频了吗?它应该可以回答您的问题。
    • 我在海滩上,我会在 WiFi 上看到一次,抱歉... :-)
    【解决方案3】:

    我实现如下:

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

    最后一点,检查代表的宽度和高度。就我而言,我不得不再次在Loader 中设置我的代表的宽度和高度。
    祝你好运 - 穆萨维

    【讨论】:

    • 我对性能做了一些研究。看来性能非常好,不需要任何优化。
    • 在不同的 qml 文件中声明对象后,编写组件语法的原因是什么?我们不能只在加载器中使用 source: 吗?
    • 是的,你可以。我使用它是因为这样更容易出错并且可以轻松绑定其属性。
    【解决方案4】:

    现在最简单的方法是使用DelegateChooser。这也允许您编辑委托的属性,这是使用 Loader 更难做到的事情!

    受文档启发的示例:

    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
    }
    

    【讨论】:

    • 这应该是正确的答案,因为默认的 Qt 组件
    【解决方案5】:

    就你只有两种类型而言,下面的代码既易于维护又易于理解:

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

    如果类型的数量会增加,这不是一个合适的解决方案,因为它很容易导致 if 语句的地狱。

    【讨论】:

      【解决方案6】:

      当然,这是可能的。 ListView.delegate 是一种指向 Component 的指针,它将绘制项目以便您更改它。

      例如:

      Employee { id: delegateEmployee }
      Manager { id: delegateManager}
      ...
      ListView {  
          property string position   
          delegate: position == "Engineer" ? delegateEmployee : delegateManager
      }
      

      【讨论】:

      • 这并不能解决问题,因为您必须在填充列表之前定义position,因此委托将是一个类型并且不会根据项目。
      猜你喜欢
      • 2015-02-12
      • 1970-01-01
      • 1970-01-01
      • 2014-02-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-02
      相关资源
      最近更新 更多