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: parentfunction 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.2ApplicationWindow {
visible: true
width: 480
height: 640Rectangle { 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.0Item {
id: lst
anchors.fill: parentListModel { 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.2ApplicationWindow {
visible: true
width: 480
height: 640Rectangle { 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.0Item {
id: lst
anchors.fill: parentListModel { 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 Filefunction callback1() { console.log("callback1");}
function callback2() { console.log("callback2");}function callbackHandle(callback) { this.call(callback);}
@@
import QtQuick 2.2
import QtQuick.Controls 1.2ApplicationWindow {
visible: true
width: 480
height: 640Rectangle { 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 HANDLEItem {
id: lst
anchors.fill: parentListModel { 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.