从QML ListView委托调用JavaScript对象方法
我有一个带有JavaScript对象列表的ListView作为模型。代理需要响应单击,我希望存储附加到模型项的单击处理程序(从QML ListView委托调用JavaScript对象方法,javascript,qt,qml,Javascript,Qt,Qml,我有一个带有JavaScript对象列表的ListView作为模型。代理需要响应单击,我希望存储附加到模型项的单击处理程序(actionproperty): 但是当我点击一个项目时,我得到 TypeError:对象[object]的属性“action”不是函数 将函数附加到对象并调用它的正确方法是什么?不幸的是,无法将函数存储在: 值必须是简单常量;字符串(带引号,可选) 在对QT_TR_NOOP)、布尔值(真、假)、数字、, 或枚举值(如AlignText.AlignHCenter) 从委托调
action
property):
但是当我点击一个项目时,我得到
TypeError:对象[object]的属性“action”不是函数
将函数附加到对象并调用它的正确方法是什么?不幸的是,无法将函数存储在: 值必须是简单常量;字符串(带引号,可选) 在对QT_TR_NOOP)、布尔值(真、假)、数字、, 或枚举值(如AlignText.AlignHCenter) 从委托调用函数的一种简单方法是将函数保持在模型之外,并在模型中引用其名称:
ListView {
id: idListView
readonly property var actions: {
"action1": function() {
console.log("called action 1!");
},
"action2": function() {
console.log("called action 2!");
}
}
model: [
{
name: "Item 1",
icon: "icon1.svg",
action: "action1"
},
{
name: "Item 2",
icon: "icon2.svg",
action: "action2"
},
/* other items */
]
delegate: MyDelegate {
name: modelData.name
icon: modelData.icon
MouseArea {
anchors.fill: parent
onClicked: {
if (typeof idListView.actions[modelData.action] === "function") {
idListView.actions[modelData.action]()
}
}
}
}
}
您应该将函数定义为QML属性
Object
不允许这样做,因此您可以使用ListModel
:
import QtQuick 2.11
import QtQuick.Window 2.11
Window {
id: root
visible: true
width:480
height: 640
title: qsTr("Hello World")
ListView {
anchors.fill: parent
spacing: 2
model: ListModel {
ListElement {
name: "Item 1"
property var func: function(){ console.log("Item 1 clicked"); }
}
ListElement {
name: "Item 2"
property var func: function(){ console.log("Item 2 clicked"); }
}
}
delegate: Rectangle {
height: 30
color: "#EFEFEF"
border { width: 1; color: "#CCC" }
width: parent.width
Text {
text: name
anchors.centerIn: parent
}
MouseArea {
anchors.fill: parent
onClicked: {
if(typeof func === "function")
func();
else
console.error("Click handler not defined");
}
}
}
}
}
另一个有点诡计的解决方案:
import QtQuick 2.11
import QtQuick.Window 2.11
Window {
id: root
visible: true
width:480
height: 640
title: qsTr("Hello World")
ListView {
anchors.fill: parent
spacing: 2
property list<QtObject> arr: [
QtObject {
property string name: "Item 1"
property var func: function(){ console.log("Item 1 clicked"); }
},
QtObject {
property string name: "Item 2"
property var func: function(){ console.log("Item 2 clicked"); }
}
]
model: arr
delegate: Rectangle {
height: 30
color: "#EFEFEF"
border { width: 1; color: "#CCC" }
width: parent.width
Text {
text: modelData.name ? modelData.name : "Undefined item"
anchors.centerIn: parent
}
MouseArea {
anchors.fill: parent
onClicked: {
if(typeof modelData.func === "function")
modelData.func();
else
console.error("Click handler not defined");
}
}
}
}
}
导入QtQuick 2.11
导入QtQuick.Window 2.11
窗口{
id:根
可见:正确
宽度:480
身高:640
标题:qsTr(“你好世界”)
列表视图{
锚定。填充:父级
间距:2
财产清单:[
QtObject{
属性字符串名称:“项1”
属性var func:function(){console.log(“单击项目1”);}
},
QtObject{
属性字符串名称:“项2”
属性var func:function(){console.log(“单击项目2”);}
}
]
型号:arr
代表:矩形{
身高:30
颜色:“EFEFEF”
边框{宽度:1;颜色:“#CCC”}
宽度:parent.width
正文{
text:modelData.name?modelData.name:“未定义项”
anchors.centerIn:父对象
}
鼠耳{
锚定。填充:父级
再次点击:{
if(typeof modelData.func==“函数”)
modelData.func();
其他的
控制台。错误(“未定义单击处理程序”);
}
}
}
}
}
我遇到了类似的问题。我想要一个抽屉
包含动作
的列表视图
。一些尝试和错误,终于让它运行(Qt5.11)。也许我的代码对其他人有用
Action {
id: aboutAction
text: "About"
icon.source: "icon_info.png"
}
Drawer {
edge: Qt.LeftEdge
width: Screen.pixelDensity * 100 // mm
height: parent.height
ListView {
id: listView
anchors.fill: parent
model: ListModel {}
delegate: ItemDelegate {
width: parent.width
action: action_
}
}
Component.onCompleted: {
listView.model.append({action_: aboutAction});
}
}
谢谢你的建议!所以,不管模型类型如何,模型项都会转换为列表元素?不,我不这么认为。我想奥格是指福利比斯的回答,我不确定。我使用了
liselement
的文档,因为我认为它与使用对象作为模型的行为相同(具有相同的可能值)。但是我不知道如何使用对象VSListModel
来管理模型。无论如何,我没有想到使用属性,如果您不介意使用ListModel
的话,我发现fobilis的答案是一个很好的选择,因为您不必依赖函数名!多谢!以上是唯一的解决方法。您是否测试了第一个代码段?我认为函数不能在liselement
中使用。是的,在5.11中测试过。首先,我发布了第二个示例,使用QtObject
s,然后我决定用liselement
尝试同样的方法,并惊讶地发现它是有效的。一个ListElement
只能有简单的类型,但对property
:-)直接使用ListElement对我不起作用,因为它不能处理QmlEngine动态重传。第二个选项看起来不错(而且很有效),尽管更加详细-我正在寻找一种将处理程序附加到模型项的方法。它在Qt 5.11中确实是新的:-“从Qt 5.11 ListElement开始还允许将函数声明分配给角色。这允许使用可调用操作定义ListElement。”第一个变量在5.12中仍然返回错误:liselement:无法对属性值使用脚本。这里应该有什么正确的语法?文件中没有样本。
Action {
id: aboutAction
text: "About"
icon.source: "icon_info.png"
}
Drawer {
edge: Qt.LeftEdge
width: Screen.pixelDensity * 100 // mm
height: parent.height
ListView {
id: listView
anchors.fill: parent
model: ListModel {}
delegate: ItemDelegate {
width: parent.width
action: action_
}
}
Component.onCompleted: {
listView.model.append({action_: aboutAction});
}
}