英文:
How to set value to a model from the property?
问题
我想根据操作系统向`ListView`模型添加不同的文件:
```qml
ApplicationWindow {
id: window
readonly property string settingsFile: (Qt.platform.os === "android") ? "qrc:/huts/qml/settings-android.qml" : "qrc:/huts/qml/settings.qml"
Drawer {
ListView {
id: listView
model: ListModel {
ListElement { title: qsTr("Port Settings"); source: window.settingsFile }
ListElement { title: qsTr("Terminal"); source: "qrc:/huts/qml/terminal.qml" }
}
...
}
...
但是我收到了一个错误:
>"ListElement: cannot use script for property value"
如何实现这个目标?
<details>
<summary>英文:</summary>
I want to add different files to the `ListView` model depending on the OS:
ApplicationWindow {
id: window
readonly property string settingsFile: (Qt.platform.os === "android") ? "qrc:/huts/qml/settings-android.qml" : "qrc:/huts/qml/settings.qml"
Drawer {
ListView {
id: listView
model: ListModel {
ListElement { title: qsTr("Port Settings"); source: window.settingsFile }
ListElement { title: qsTr("Terminal"); source: "qrc:/huts/qml/terminal.qml" }
}
...
}
...
But I get an error:
>"ListElement: cannot use script for property value"
How can this goal be achieved?
</details>
# 答案1
**得分**: 1
最简单的方法是在javascript函数中追加项目。在追加时可以使用脚本值。
ListModel
{
id: listModel
Component.onCompleted:
{
listModel.append({
title: qsTr("端口设置"),
source: window.settingsFile
});
listModel.append({
title: qsTr("终端"),
source: "qrc:/huts/qml/terminal.qml"
});
}
}
英文:
The easiest way to do this is to append items in a javascript function. You can use script values when appending.
ListModel
{
id: listModel
Component.onCompleted:
{
listModel.append({
title: qsTr("Port Settings"),
source: window.settingsFile
});
listModel.append({
title: qsTr("Terminal"),
source: "qrc:/huts/qml/terminal.qml"
});
}
}
答案2
得分: 1
对于你的问题中涉及到的Android部分,你可以利用+android
文件选择器:
huts/qml/terminal.qml
huts/qml/+android/terminal.qml
也就是说,当你在QML中使用"huts/qml/terminal.qml"
时,QML会在Android上自动加载专门针对Android的文件,而在其他情况下则加载默认的文件。
至于你的ListModel,在QML中不允许使用表达式进行初始化,因此无法在声明时访问变量或使用qsTr()。如其他答案所建议,你可以在代码中实现。你可以通过声明一个JavaScript对象并从该对象初始化你的ListModel来在声明性和命令性之间取得更好的平衡,例如:
ListView {
id: listView
model: ListModel {
property var _data: [
{ title: qsTr("Port Settings"), source: "huts/qml/settings.qml" },
{ title: qsTr("Terminal"), source: "huts/qml/terminal.qml" }
]
Component.onCompleted: { for (let obj of _data) append(obj) }
}
delegate: ItemDelegate { text: title }
}
注意:在你的QML中使用qrc:/
可能并不是必要的,因为你的主应用程序很可能已经是一个qrc:
资源了,所以只需使用相对引用来指向你的主文件所在的位置即可。因此,使用"huts/qml/settings.qml"
而不是"qrc:/huts/qml/settings.qml"
即可。
参考资料:
- https://doc.qt.io/qt-6/qqmlfileselector.html
- https://doc.qt.io/qt-6/qfileselector.html
- https://doc.qt.io/qt-6/qtquickcontrols-fileselectors.html
英文:
For the Android part of your question, you should take the opportunity to use +android
file selectors:
huts/qml/terminal.qml
huts/qml/+android/terminal.qml
i.e. when you use "huts/qml/terminal.qml"
in QML, QML will automatically load the Android specialized file on Android and load the other by default.
As to your ListModel, QML does not permit you to initialize it using expressions, so accessing variables or using qsTr() both are not permitted declaratively. As suggested by the other answer you can do it in code. You can strike a higher balance between declarative and imperative, by declaring a JavaScript object and initialize your ListModel from the object, e.g.
ListView {
id: listView
model: ListModel {
property var _data: [
{ title: qsTr("Port Settings"), source: "huts/qml/settings.qml" },
{ title: qsTr("Terminal"), source: "huts/qml/terminal.qml" }
]
Component.onCompleted: { for (let obj of _data) append(obj) }
}
delegate: ItemDelegate { text: title }
}
N.B. the use of "qrc:/" in your QML may not be necessary, since your main application is probably a "qrc:" resource already, so, it is enough to use a relative reference to where your main file is. So "huts/qml/settings.qml" instead of "qrc:/huts/qml/settings.qml"
References:
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论