首页 > 解决方案 > 从 QML ListView 委托调用 JavaScript 对象方法

问题描述

我有一个带有 JavaScript 对象列表的 ListView 作为模型。委托需要响应点击,我想存储附加到模型项(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()
            }
        }
    }
}

但是当我点击一个项目时,我得到

TypeError:对象 [object Object] 的属性“操作”不是函数

将函数附加到对象并调用它的正确方法是什么?

标签: javascriptqtqml

解决方案


您应该将函数定义为 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");
                }
            }
        }
    }
}

推荐阅读