如何使用条件子结构为ListView中的异构列表创建QML委托

时间:2018-04-14 23:09:58

标签: qt qml

我有一个(大的)异构的'我想在QML ListView中查看的json对象列表,例如

[ 
  {"type": "person", "first_name": "John", "last_name": "Smith"},
  {"type": "doggie", "breed": "Maltese", "nickname": "Roger"},
  {"type": "person", "first_name": "Jane", "last_name": "Smith"},
  {"type": "fruit" , "color": "red"},
  ...
]

我想创建一个智能呈现这些项目的委托,根据'类型'进行调度。字段到知道如何正确呈现特定类型的子组件。

理想情况下,我正在寻找一种模块化的解决方案(例如,以一种可单独测试的方式为每种类型创建一个组件),然后让ListView委托在这些选择中用最简单的语法进行选择,这种语法是高效的和惯用的。

我应该怎么做呢?特别是,如何创建具有条件结构的QML小部件?

谢谢!

1 个答案:

答案 0 :(得分:1)

  

最简单的语法是高性能和惯用的

"表演者"部分可能有点问题,因为JS数组作为模型是一种快速而肮脏的方法,效率不高,特别是如果你有数据更改。

您还可以使用ListModel并运行一个简单的循环来使用JSON对象填充它,但请注意,这将涉及动态角色,这些角色会带来开销。

话虽如此,你可以通过简单地使用加载器在视图委托中实例化一个专门的子项来避免这一切:

  property var mdata: [
    {"type": "person", "first_name": "John", "last_name": "Smith"},
    {"type": "doggie", "breed": "Maltese", "nickname": "Roger"},
    {"type": "person", "first_name": "Jane", "last_name": "Smith"},
    {"type": "fruit" , "color": "red"},
  ]

  ListView {
    anchors.fill: parent
    model: mdata
    delegate: Loader {
      source: modelData.type + ".qml"
    }
  }

然后您将拥有person.qmldoggie.qml等等,它们可以以相同的方式连接到数据:

// person.qml
Rectangle {
    width: 200
    height: 50
    color: "yellow"
    Text {
      anchors.centerIn: parent
      text: modelData.first_name + " " + modelData.last_name + ", a person"
    }
}

这种方法通过完全避免角色来避免使用动态角色,而是使用modelData,这与在委托中使用model[index]实际上是一样的。

请注意,名称未大写的qml文件无法以声明方式实例化,因此如果由于某种原因需要这样做,则应以这种方式实现它们并将type对象属性的值大写,以便可以解析它