从QML ListView委托调用JavaScript对象方法

时间:2018-05-31 11:10:05

标签: javascript qt qml

我有一个ListView,其中包含JavaScript对象列表作为模型。委托需要响应click,我想存储附加到模型项(action属性)的click处理程序:

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:Property' action'对象[object Object]不是函数

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

3 个答案:

答案 0 :(得分:2)

不幸的是,无法在ListElement中存储函数:

  

值必须是简单的常量;两个字符串(引用和可选   在调用QT_TR_NOOP),布尔值(true,false),数字,   或枚举值(例如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]()
                }
            }
        }
    }
}

答案 1 :(得分:2)

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

答案 2 :(得分:0)

我遇到了类似的问题。我想拥有一个DrawerListView的{​​{1}}。一些尝试和错误,最后使它运行(Qt 5.11)。愿我的代码对其他人有用。

Action