如何从另一个 QML 访问和控制 ListModel 的内容
How to access and control the content of a ListModel from another QML
我问过类似的问题。但此解决方案仅适用于 one-paged QML 文件。我构建了一个包含许多页面的 QML 应用程序,因此我制作了一个包含 Add/Remove 操作的收藏夹选项卡。最喜欢的标签页中有一个列表模型。在我看来,为了将任何页面添加到收藏夹列表,有必要从示例页面调用收藏夹列表模型,因此当用户单击该操作时,该页面应作为列表项添加到收藏夹页面.我有两个例子。第一个例子是 one-paged QML 和它 adds/removes 列表项。但是第二个示例没有 adds/removes 收藏列表页面的示例页面。如何使用 QML 或 Java 脚本访问、保存和恢复列表模型的内容?谢谢。
第一个例子:
main.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
}
第二个例子:
main.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{}
}
}
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 库,因为制作列表菜单很简单。
在你的代码中你有 2 个问题:
- 首先是你没有在
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
.[=29= 中删除 non-existent 数据]
更新:
Settings
用于存储数据并在关闭应用程序后能够恢复,但是如果你想在多个文件之间共享数据,一个可能的解决方案是实现一个singleton
,如这是整个应用程序中存在的单个元素。在任何地方修改它都会很容易。
为了构建单例,我们创建一个具有以下结构的 .qml 文件:
Shared.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()
例如在您的具体情况下:
main.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")
}
]
}
Favourites.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
我问过类似的问题
第一个例子:
main.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
}
第二个例子:
main.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{}
}
}
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 库,因为制作列表菜单很简单。
在你的代码中你有 2 个问题:
- 首先是你没有在
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
.[=29= 中删除 non-existent 数据]
更新:
Settings
用于存储数据并在关闭应用程序后能够恢复,但是如果你想在多个文件之间共享数据,一个可能的解决方案是实现一个singleton
,如这是整个应用程序中存在的单个元素。在任何地方修改它都会很容易。
为了构建单例,我们创建一个具有以下结构的 .qml 文件:
Shared.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()
例如在您的具体情况下:
main.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")
}
]
}
Favourites.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