[英]Calling JavaScript object method from QML ListView delegate
I have a ListView with a list of JavaScript objects as a model. 我有一个带有JavaScript对象列表的ListView作为模型。 The delegate needs to respond to click and I want to store click handler attached to model item (
action
property): 委托需要响应点击,我想存储附加到模型项(
action
属性)的点击处理程序:
ListView {
id: idListView
model: [
{
name: "Item 1",
icon: "icon1.svg",
action: function() {
//do stuff
}
},
/* other items */
]
delegate: MyDelegate {
name: modelData.name
icon: modelData.icon
MouseArea {
anchors.fill: parent
onClicked {
modelData.action()
}
}
}
}
But when I click on an item i get 但是当我点击一个项目我得到
TypeError: Property 'action' of object [object Object] is not a function
TypeError:对象[object Object]的属性'action'不是函数
What's the proper way to attach function to object and call it? 将函数附加到对象并调用它的正确方法是什么?
Unfortunately it is not possible to store a function inside a ListElement
: 不幸的是,不可能在
ListElement
内存储一个函数:
Values must be simple constants;
值必须是简单常量; either strings (quoted and optionally within a call to QT_TR_NOOP), boolean values (true, false), numbers, or enumeration values (such as AlignText.AlignHCenter).
字符串(带引号,并且可以选择在调用QT_TR_NOOP的情况下),布尔值(真,假),数字或枚举值(例如AlignText.AlignHCenter)。
A simple way to call a function from a delegate is to keep the function outside of the model and reference its name in the model: 从委托调用函数的一种简单方法是将函数保留在模型之外,并在模型中引用其名称:
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]()
}
}
}
}
}
You should define function as a QML property. 您应该将函数定义为QML属性。
Object
doesn't allow that so you could use ListModel
instead: 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");
}
}
}
}
}
Another but a bit tricked solution: 另一个但有些欺骗的解决方案:
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");
}
}
}
}
}
I ran into a similar issue. 我遇到了类似的问题。 I wanted to have a
Drawer
containing a ListView
of Action
s. 我想要一个包含
Action
的ListView
的Drawer
。 Some try and error and finally got it running (Qt 5.11). 一些尝试和错误,最后使它运行(Qt 5.11)。 May my code is of use for someone else.
愿我的代码对其他人有用。
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});
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.