How to append function object to an ListElement and callback when the element clicked



  • Like 'LauncherList' in Qt5.3 examples, I defined a common listview just replacing the url in function 'addExample' with a callback function object. In Component.onCompleted, use addExample to set every element's callback while clicked.
    I wanted the callback object can be called when list element clicked, but it was failed. After the callback function object append to listElement, its type was 'object', not 'function' anymore. How can I call the callback object?
    Thanks a lot!



  • If i understand it right, you have a model where you store a function in a key. Now you want to execute this function if you click on an element? For this you can use the "call":https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call function of javascript.



  • Thanks for replay!
    I think I did not use model to store function with keys.
    I just want to use it like this,

    @Item {
    height: 480
    width: 320
    LauncherList {
    id: ll
    anchors.fill: parent

        function callback1(){}
        function callback2(){}
    
        Component.onCompleted: {
            addExample("Hello1",callback1)       addExample("Hello2",callback2)
        }
    }
    

    }@

    But after pass callback1/2 to the ListElement, its type was 'object', not 'function' any more, so calling was failed



  • In JavaScript everything is an object. You can use the call function for that like i wrote in my first answer. object.call(); Please take a look into the documentation.



  • OK, I try it. Thanks. :)



  • Hi, I failed to resolved this problem at last. :(
    Here is my test code,
    main.qml
    @import QtQuick 2.2
    import QtQuick.Controls 1.2

    ApplicationWindow {
    visible: true
    width: 480
    height: 640

    Rectangle {
        anchors.fill: parent
        color: "white"
    }
    
    Cmlist {
        id: lst
        anchors.fill: parent
    
        Component.onCompleted: {
            addItem("abc", callback1)
            addItem("abc", callback1)
        }
    
        function callback1()
        {
            console.debug("callback1")
        }
        function callback2()
        {
            console.debug("callback2")
        }
    }
    

    }@

    CmList.qml
    @import QtQuick 2.0

    Item {
    id: lst
    anchors.fill: parent

    ListModel {
        id: lstmodel
    }
    
    Component {
        id: lstdelegate
    
        Rectangle {
            id: lstitem
            width: lst.width
            height: 80
            color: "steelblue"
    
            Rectangle {
                anchors.fill: parent
                color: "#7A7A7A"
                visible: mouse.pressed
            }
    
            Text {
                id: lsttext
                text: str
                anchors.verticalCenter: parent.verticalCenter
                anchors.left: parent.left
                anchors.leftMargin: 10
                font.pixelSize: parent.height * 0.5
                font.bold: true
                color: "black"
            }
    
            Rectangle {
                height: 1
                width: parent.width
                color: "lightgray"
                anchors.bottom: parent.bottom
            }
    
            signal clicked
            onClicked: {
                callback.call(this)
            }
    
            MouseArea {
                id: mouse
                anchors.left: parent.left
                anchors.right: parent.right
                anchors.top: parent.top
                anchors.bottom: parent.bottom
                onClicked: {
                    lstitem.clicked()
                }
            }
        }
    }
    
    ListView {
        id: lstview
        anchors.fill: parent
        model: lstmodel
        delegate: lstdelegate
    }
    
    function addItem(str_, callback_)
    {
        lstmodel.append({
                            "str": str_,
                            "callback": callback_
                        })
    }
    

    }
    @

    when clicked item, it will print 'qrc:///Cmlist.qml:46: TypeError: Property 'call' of object [object Object] is not a function'.

    I am a newer at Qt and also not familiar with JavaScript.
    Is the calling 'callback.call(this)' wrong ?



  • Hmm, i don't see where you get the callback from the model?



  • At 'Component.onCompleted' in the main.qml, I pass the function reference 'callback1' to the ListElement renaming 'callback', see the addItem function in 'CmList.qml'.



  • Hmm, you can try something like this:

    @
    import QtQuick 2.2
    import QtQuick.Controls 1.2

    ApplicationWindow {
    visible: true
    width: 480
    height: 640

    Rectangle {
        anchors.fill: parent
        color: "white"
    }
    
    Cmlist {
        id: lst
        anchors.fill: parent
    
        Component.onCompleted: {
            addItem(lst, "abc", "callback1")
            addItem(lst, "abc", "callback2")
        }
    
        function callback1()
        {
            console.debug("callback1")
        }
        function callback2()
        {
            console.debug("callback2")
        }
    }
    

    }
    @

    @
    import QtQuick 2.0

    Item {
    id: lst
    anchors.fill: parent

    ListModel {
        id: lstmodel
    }
    
    Component {
        id: lstdelegate
    
        Rectangle {
            id: lstitem
            width: lst.width
            height: 80
            color: "steelblue"
    
            Rectangle {
                anchors.fill: parent
                color: "#7A7A7A"
                visible: mouse.pressed
            }
    
            Text {
                id: lsttext
                text: str
                anchors.verticalCenter: parent.verticalCenter
                anchors.left: parent.left
                anchors.leftMargin: 10
                font.pixelSize: parent.height * 0.5
                font.bold: true
                color: "black"
            }
    
            Rectangle {
                height: 1
                width: parent.width
                color: "lightgray"
                anchors.bottom: parent.bottom
            }
    
            signal clicked
            onClicked: {
                cmp.call(callback)
            }
    
            MouseArea {
                id: mouse
                anchors.left: parent.left
                anchors.right: parent.right
                anchors.top: parent.top
                anchors.bottom: parent.bottom
                onClicked: {
                    lstitem.clicked()
                }
            }
        }
    }
    
    ListView {
        id: lstview
        anchors.fill: parent
        model: lstmodel
        delegate: lstdelegate
    }
    
    function addItem(cmp, str_, callback_)
    {
        lstmodel.append({
            "cmp": cmp
            "str": str_,
            "callback": callback_
        })
    }
    

    }
    @

    You see the changes? The trick is to pass the object where the functions are defined (scope) to the model and use call with a string (the name of the function). You can also pass parameters. Everything after the function name will pass as parameter like: cmp.call(callback, param1, param2,...) I'm not at home so no guaranty :)



  • Thanks a lot! But it was not work correted. The error msg:

    qrc:///Cmlist.qml:46: TypeError: Property 'call' of object Cmlist_QMLTYPE_0_QML_13(0x23ab3450) is not a function

    I also try 'addItem(lst, "abc", callback1)', still it was not corrected.



  • Sorry my fault. The problem you have a Qml Object not a JavaScript object so no call function. Hmm, one solution can be to define the callback function in a JavaScript file. Like so:

    @
    // JS File

    function callback1() { console.log("callback1");}
    function callback2() { console.log("callback2");}

    function callbackHandle(callback) { this.call(callback);}
    @

    @
    import QtQuick 2.2
    import QtQuick.Controls 1.2

    ApplicationWindow {
    visible: true
    width: 480
    height: 640

    Rectangle {
        anchors.fill: parent
        color: "white"
    }
    
    Cmlist {
        id: lst
        anchors.fill: parent
    
        Component.onCompleted: {
            addItem("abc", "callback1")
            addItem("abc", "callback2")
        }
    }
    

    }
    @

    @
    import QtQuick 2.0
    import "jsfile.js" as HANDLE

    Item {
    id: lst
    anchors.fill: parent

    ListModel {
        id: lstmodel
    }
    
    Component {
        id: lstdelegate
    
        Rectangle {
            id: lstitem
            width: lst.width
            height: 80
            color: "steelblue"
    
            Rectangle {
                anchors.fill: parent
                color: "#7A7A7A"
                visible: mouse.pressed
            }
    
            Text {
                id: lsttext
                text: str
                anchors.verticalCenter: parent.verticalCenter
                anchors.left: parent.left
                anchors.leftMargin: 10
                font.pixelSize: parent.height * 0.5
                font.bold: true
                color: "black"
            }
    
            Rectangle {
                height: 1
                width: parent.width
                color: "lightgray"
                anchors.bottom: parent.bottom
            }
    
            signal clicked
            onClicked: {
                HANDLE.callbackHandler(callback)
            }
    
            MouseArea {
                id: mouse
                anchors.left: parent.left
                anchors.right: parent.right
                anchors.top: parent.top
                anchors.bottom: parent.bottom
                onClicked: {
                    lstitem.clicked()
                }
            }
        }
    }
    
    ListView {
        id: lstview
        anchors.fill: parent
        model: lstmodel
        delegate: lstdelegate
    }
    
    function addItem(str_, callback_)
    {
        lstmodel.append({
            "str": str_,
            "callback": callback_
        })
    }
    

    }
    @



  • Thank you dasRicardo! but still has errors.
    'qrc:///func.js:4: TypeError: Property 'call' of object [object Object] is not a function'

    Now I used switch case to call different functions.
    In
    @signal clicked
    onClicked: {
    onElementClicked(callback_key)
    }@
    always call the same interface.
    onElementClicked is defined at where I using the list view.

    I just confused why some type like 'string' or 'int' can keep its real type after listview.append, but funtion type can not.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.