QML | ListModel中的持久性内存(存储ListModel以便以后使用)

时间:2019-09-06 20:16:43

标签: json qt qml listmodel

给出一个ListModel包含多层存储的信息(存储在元素中的元素数组),有没有办法存储模型并在以后调用它?

我尝试将ListModel存储为JSON字符串,但它无法跟踪子对象。例如,在以下代码段中,输出告诉我存在一个“ kids”对象,但不了解“ kid1”或“ kid2”。 “存储”对象也是如此,但是对“ duck1”或“ duck2”一无所知。

  <xsl:template match="products">
    <channel>
        <description>Testing Description</description>
        <xsl:apply-templates/>
    </channel>
  </xsl:template>

  <xsl:template match="product">
      <xsl:for-each-group select="." group-by="let $keys := categories/category/categoryname/substring-after(., ' &gt; ') return if (exists($keys)) then $keys else ''">
          <item>
              <id>{productid}_{position()}</id>
              <item_group_id>{productid}</item_group_id>
              <product_type>{current-grouping-key()}</product_type>
          </item>
      </xsl:for-each-group>
  </xsl:template>

以下是输出,该输出无法显示有关子对象的任何信息。我希望“父母”对象下有“ kid1”和“ kid2”。

import QtQuick 2.9
import QtQuick.Window 2.2

Window {
    visible: true
    width: 640
    height: 480

    ListModel {
        id: listModel
        ListElement {
            name: "Parent"
            kids: [
                ListElement {kid: "kid1"},
                ListElement {kid: "kid2"}
            ]
        }
        ListElement {
            name: "store"
            ducks: [
                ListElement {duck: "duck1"},
                ListElement {duck: "duck2"}
            ]
        }

        Component.onCompleted: {
            var datamodel = []
            for (var i = 0; i < this.count; ++i)
                datamodel.push(this.get(i))
            console.log(JSON.stringify(datamodel))
        }
    }
}

编辑:我希望输出更加像这样:

[
  {
    "kids": {
      "objectName": "",
      "count": 2,
      "dynamicRoles": false
    },
    "name": "Parent"
  },
  {
    "name": "store",
    "ducks": {
      "objectName": "",
      "count": 2,
      "dynamicRoles": false
    }
  }
]

2 个答案:

答案 0 :(得分:1)

似乎您想在关闭应用程序时保存模型的当前状态,并在再次启动应用程序时将其恢复。绝对必须能够对模型进行序列化和反序列化。

[1/2]仅基于Qml的实现

  1. 使用this中的this序列化器,请回答,假设您不介意绑定到第三方许可证(此许可证是完全免费的,代码似乎可靠,但我尚未尝试或测试过它)。然后使用JSON.parse从字符串版本重新创建对象。
  2. 制作自己的(反)序列化器,并确保它与您使用的实际模型紧密相关。例如,如果并非需要备份/还原模型中对象的所有属性,那么直接查找所需的属性并仅使用它们就更明智了。这可能会大大降低搜索属性层次结构的开销,但是您将获得一个非常特定的(反)序列化器,该序列化器无法在项目中重复使用。

[2/2] Qml / C ++实现

在时间允许的情况下,另一种解决方案是在C ++方面设计模型并将其按原样或作为QVariant公开给Qml代码。然后,将反序列化委托给C ++代码。优点是:代码更简洁,I / O操作更快。缺点是:这需要更多的时间来实施,如果整个应用程序对功能的要求不高,我认为这将不必要地复杂化。

答案 1 :(得分:1)

借助misterFad的链接,我创建了一个特定于我的应用程序的serialize()函数。发布代码以激发潜在的其他人的直觉。

import QtQuick 2.9
import QtQuick.Window 2.2

Window {
    visible: true
    width: 640
    height: 480


    function serialize(object) {
        var model = object
        var totalText = "["

        for(var i = 0; i < model.count; i++) {
            var element = model.get(i)
            totalText += "{\"name\": \"" + element.name + "\""

            if(element.kids.count) totalText += ",\"kids\": " + serialize(element.kids)
            totalText += "}" + (i < model.count-1 ? ",": "")
        }

        return totalText + "]"
    }

    ListModel {
        id: listModel
        ListElement {
            name: "dad"
            kids: [
                ListElement {
                    name: "kid1";
                    kids: []
                },
                ListElement {
                    name: "kid2";
                    kids: [
                        ListElement {name: "grandkid1"; kids: []},
                        ListElement {name: "grandkid2"; kids: []}
                    ]
                }
            ]
        }
        ListElement {
            name: "store"
            kids: [
                ListElement {name: "duck1"; kids: []},
                ListElement {name: "duck2"; kids: []}
            ]
        }
        Component.onCompleted: console.log(serialize(listModel))
    }
}

输出JSON为:

[
  {
    "name": "dad",
    "kids": [
      {
        "name": "kid1"
      },
      {
        "name": "kid2",
        "kids": [
          {
            "name": "grandkid1"
          },
          {
            "name": "grandkid2"
          }
        ]
      }
    ]
  },
  {
    "name": "store",
    "kids": [
      {
        "name": "duck1"
      },
      {
        "name": "duck2"
      }
    ]
  }
]