qt - 如何从另一个 QML 访问和控制 ListModel 的内容

标签 qt qml settings

我问过类似的问题here 。但该解决方案仅适用于单页 QML 文件。我构建了一个包含许多页面的 QML 应用程序,因此我制作了一个包含添加/删除操作的最喜欢的选项卡。收藏夹标签页中有一个列表模型。在我看来,为了将任何页面添加到收藏夹列表,有必要从示例页面调用收藏夹列表模型,因此当用户单击该操作时,该页面应该作为列表项添加到收藏夹页面。我有两个例子。第一个示例是单页 QML,它添加/删除列表项。但第二个示例不会将示例页面添加/删除到收藏夹列表页面。如何使用 QML 或 JavaScript 访问、保存和恢复列表模型的内容?谢谢。

第一个示例:

enter image description here

ma​​in.qml

import QtQuick 2.6
import QtQuick.Controls 2.3
import QtQuick.Controls.Material 2.0
import Qt.labs.settings 1.0
ApplicationWindow{
    id:main
    width: 640
    height: 480
    visible:true
    title: "Menu"
    property string datastore: ""
    property int countt2: 0
    Settings{
        property alias datastore: main.datastore
        property alias mycount: main.countt2
    }
    menuBar:MenuBar {
        Menu{
        title: main.title
            Action {
                id:action2
                text: qsTr("On/Off")
                onTriggered:{
                    countt2++
                    console.log("triggered works.Count/2: "+ countt2%2)
                    if(countt2%2==1){
                        console.log("it must be added")
                        dataModel.append({ "title": "Application Tools" })
                    }
                    else if(countt2%2==0){
                        console.log("list must be removed. count/2: "+countt2%2)
                        return dataModel.remove(dataModel.index)
                    }
                }
            }
        }
    }
    Component.onCompleted: {
        if(datastore){
            dataModel.clear()
            var datamodel=JSON.parse(datastore)
            for (var i=0; i<datamodel.length; ++i) dataModel.append(datamodel[i])
        }
        console.log("onCompleted works right now.")
    }
    onClosing: {
        var datamodel = []
        for (var i=0;i<dataModel.count; ++i) datamodel.push(dataModel.get(i))
        datastore=JSON.stringify(datamodel)
        console.log("datastore: "+datastore)
    }
        ListView {
            id:malist
            width: parent.width
            height: parent.height
            focus: true
            interactive: true
            clip: true
            model:FavModel{
            id:dataModel
            }
            delegate: ItemDelegate {
                width: parent.width
                text: model.title
            }
        }
}

FavModel.qml:

import QtQuick 2.0
ListModel {
    id:dataModel
    }

第二个示例:

enter image description here

enter image description here

ma​​in.qml:

import QtQuick 2.6
import QtQuick.Controls 2.2
import QtQuick.Controls.Material 2.0
import QtQuick.Layouts 1.3
import Fluid.Controls 1.0
import QtQuick.Window 2.3
ApplicationWindow{
    id:main
    width: 640
    height: 480
    visible:true
    title: "Example App"
    initialPage:TabbedPage {
        title: main.title
        Tab{
            title:"APPS"
        ListView {
            id:malist
            width: parent.width
            height: parent.height
            focus: true
            interactive: true
            clip: true
            model:ListModel {
            id:appModel
            ListElement { title: qsTr("Page1"); source: "qrc:/SampePage.qml" }
            }
            delegate: ListItem {
                text: model.title
                onClicked: pageStack.push(model.source)
            }
        }
        }
        Favourites{}
    }
}

收藏夹.qml:

import QtQuick 2.6
import QtQuick.Controls 2.0
import QtQuick.Controls.Material 2.0
import Fluid.Controls 1.0
Tab{
    title:"FAVORITES"
ListView {
    id:favorites
    width: parent.width
    height: parent.height
    focus: true
    interactive: true
    clip: true
    model:FavModel {
    id:favModel
    }
    delegate: ListItem {
        text: model.title
        onClicked: pageStack.push(model.source)
    }
}
}

FavModel.qml:

import QtQuick 2.0

ListModel {
    id:dataModel
    }

SamplePage.qml:

import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Controls.Material 2.2
import Fluid.Controls 1.0
import Qt.labs.settings 1.0
Page{
    title:qsTr("Page1")
    appBar.maxActionCount: 2
    id:sampleapp
    property string datastore: ""
    property int countt2: 0
    Settings{
        id:mysetting4
        property alias datastore: sampleapp.datastore
        property alias mycount: sampleapp.countt2
    }
    FavModel{
        id:dataModel
    }
    Component.onCompleted: {
        console.log("onCompleted works right now.")
        if(datastore){
            dataModel.clear()
            var datamodel = JSON.parse(datastore)
            for (var i=0; i<datamodel.length; ++i) dataModel.append(datamodel[i])
        }
    }
    onCanGoBackChanged: {
        var datamodel=[]
        for (var i=0; i<dataModel.count; ++i) datamodel.push(dataModel.get(i))
        datamodel = JSON.stringify(datamodel)
        console.log("datastore: "+datastore)
    }
    actions: [
        Action {
          id:favourite2
            onTriggered:{
                countt2++
                console.log("Count/2: "+ countt2%2)
                if(countt2%2==1){
                    console.log("List must be added")
                    dataModel.append({ "title": "Application Tools", "source": "qrc:/SampePage.qml" })
                }
                else if(countt2%2==0){
                    console.log("List must be removed.")
                    return dataModel.remove(dataModel.index)
                }
            }
            icon.name: "toggle/star"
            toolTip: qsTr("Add/Remove")
        }
    ]
}

*我无法在第二个示例中仅使用 Qt Quick Controls 2.0 示例,我必须使用 Fluid qml 库,因为制作列表菜单很简单。

最佳答案

在您的代码中,您有两个问题:

  • 首先是您没有将列表保存在 datastorage

[...]
datamodel = JSON.stringify(datamodel)
[...]

必须是:

datastore = JSON.stringify(datamodel)
  • 第二个是您在错误的时间保存数据,onCanGoBackChanged事件在页面加载后发生。一般来说,做法必须是在item加载完成时加载数据,在item销毁之前保存数据,所以使用Component.onCompleted比较合适。和Component.onDestruction事件。

Component.onCompleted: {
    console.log("onCompleted works right now.")
    if(datastore){
        dataModel.clear()
        var datamodel = JSON.parse(datastore)
        for (var i=0; i<datamodel.length; ++i) dataModel.append(datamodel[i])
    }
}
Component.onDestruction: {
    console.log("onDestruction works right now.")
    var datamodel=[]
    for (var i=0; i<dataModel.count; ++i) datamodel.push(dataModel.get(i))
    datastore = JSON.stringify(datamodel)
    console.log("datastore: "+datastore)
}

另一个小错误,因为我认为这是一个测试代码。假设 dataModel 中没有数据那countt2是偶数,因此您需要从 dataModel 中删除不存在的数据。 .

更新:

Settings用于存储数据并能够在关闭应用程序后恢复,但如果您想在多个文件之间共享数据,一个可能的解决方案是实现 singleton ,因为这是整个应用程序中存在的单个元素。在任何地方都可以轻松修改它。

为了构建单例,我们创建一个具有以下结构的 .qml 文件:

共享.qml

pragma Singleton
import QtQuick 2.0

QtObject {
    property var favModel: FavModel{}
}

然后我们添加另一个名为 qmldir 的文件:

qmldir

singleton Shared 1.0 Shared.qml

然后我导入它并按以下方式使用它:

import "."

[...]

Shared.favModel.some_function()

例如,在您的具体情况下:

ma​​in.qml

import QtQuick 2.6
import QtQuick.Controls 2.2
import QtQuick.Controls.Material 2.0
import QtQuick.Layouts 1.3
import Fluid.Controls 1.0
import QtQuick.Window 2.3
import Qt.labs.settings 1.0
import "."

ApplicationWindow{
    id:main
    width: 640
    height: 480
    visible:true
    title: "Example App"

    property string datastore: ""
    Settings{
        property alias datastore: main.datastore
    }

    Component.onCompleted: {
        console.log("onCompleted works right now.")
        if(datastore){
            Shared.favModel.clear()
            var datamodel = JSON.parse(datastore)
            for (var i=0; i<datamodel.length; ++i) Shared.favModel.append(datamodel[i])
        }
    }

    Component.onDestruction: {
        console.log("onDestruction works right now.")
        var datamodel=[]
        for (var i=0; i<Shared.favModel.count; ++i) datamodel.push(Shared.favModel.get(i))
        datastore = JSON.stringify(datamodel)
        console.log("datastore: "+datastore)
    }
    [...]
}

SamplePage.qml

import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Controls.Material 2.2
import Fluid.Controls 1.0
import "."

Page{
    title:qsTr("Page1")
    appBar.maxActionCount: 2
    id:sampleapp

    actions: [
        Action {
            id:favourite2
            onTriggered:{
                Shared.favModel.append({ "title": "Application Tools", "source": "qrc:/SamplePage.qml" })
            }
            icon.name: "toggle/star"
            toolTip: qsTr("Add/Remove")
        }
    ]
}

收藏夹.qml

import QtQuick 2.6
import QtQuick.Controls 2.0
import QtQuick.Controls.Material 2.0
import Fluid.Controls 1.0

import "."

Tab{
    title:"FAVORITES"
    id:favtab

    ListView {
        id:favorites
        width: parent.width
        height: parent.height
        focus: true
        interactive: true
        clip: true
        model: Shared.favModel
        delegate: ListItem {
            text: model.title
            onClicked: pageStack.push(model.source)
        }
    }
}

完整且更新的示例可以在下面的 link 中找到。

关于qt - 如何从另一个 QML 访问和控制 ListModel 的内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48891034/

相关文章:

javascript - 如何在 iOS 9.3+ 上从网页打开 Safari 的设置

.net - 如何在 .net 中的不同程序集版本之间保留 user.config 设置?

c# - Properties.Settings.Default 存储在哪里?

c++ - 如何隐藏 QTreeView 中的某些列?

qt - Qt/QML 中的下拉刷新 ListView

qt - 如何以编程方式创建选项卡的项目?

c++ - 如何在 cmake 中使用 QML_ELEMENT

c++ - 项目错误 : Unknown module(s) in QT: quick

c++ - Qt4:从 QAbstractTableModel 中读取默认的 mimeData

python - 布局内容更改后将 QMainWindow 调整为最小尺寸