QML:如何将JavaScript函数作为参数传递到另一个函数中

6

我有一段QML代码,例如下面这段代码:

Item {
    id:self;

    function update(){
        var visitFunc = self.applyUpdate;

        innerTraversal(self,visitFunc);
    }

    function reset(){
         var visitFunc = self.applyReset;
        innerTraversal(self,visitFunc);
    }

    function innerTraversal(obj, visitFun){
        console.log(typeof visitFun);

        if(obj!== self && visitFun && typeof visitFun ==="function")
           visitFun(obj);

        if(hasChilderns(obj)){
            var objChilderns = obj.children;

            for(var i=0 ; i< objChilderns.length ; i++){
                innerTraversal(objChilderns[i]);
            }
        }
    }

    function hasChilderns(obj){
        if(typeof obj.children !== 'undefined')
            return true;
        else
            return false;
    }

    function applyReset(obj){
        if(typeof obj.reset === 'function')
            obj.reset();
    }

    function applyUpdate(obj){
        if(typeof obj.update === 'function')
            obj.update();
    }
}

在普通的javascript中这个代码很有效,但是当我在QML中使用这段代码时,visitFun总是类型为undefined,它不能工作。你有什么好主意使它工作吗?
3个回答

7
在QtQuick 2中,您应该能够使用绑定函数来绑定属性。
Item {  //<-- declaration
  id : item
  property variant fun 
}
item.fun : Qt.binding(function(){doSomething()})  //<--defintion

item.fun // <-- invocation without braces 

您可以将一个带有通用函数作为参数的对象传递。

通常,函数重载也可以用于创建通用函数,例如创建一个按钮类型:

---Button.qml
Item {
  function fun() {}  //<-- declaration (empty dummy)
  MouseArea {
    anchors.fill: parent
    onClicked: {
      fun();    //<-- invocation
    }
  }
}
---
---main.qml---
Button {
id: button
  function fun() {  //<-- defintion by overloading
    doSomething
  }
}
---

点击按钮将激活它的onClick处理程序并实际执行某些操作;)。然后,您将传递具有通用函数的对象而不是函数本身。


1
在QML内部,您的“self”类型为“QQuickItem”,而普通JS对象(例如使用“new Object()”或“{prop:value}”创建的对象)类型为QJsValue。并且“self”不是变量名,而是QML id,请记住这种区别。
在QML中,信号/插槽或属性绑定的使用可以比传递回调函数更加强大。使用“typeof”也是一种不好的做法(据我所知,在“普通”JS中也是如此),您可以简单地编写类似以下内容的代码:
// Or simply "return obj.children" - but function become useless than.
if(obj.children)
        return true;
    else
        return false;

但是这段代码仍然无用 - QML中的Item属性"children"具有类型"list",它总是存在的。
因此我的结论是 - 在编写代码之前,你应该尝试学习一些QML基础知识。

谢谢,我很感激你的回答,但将函数作为参数传递是JavaScript的重要部分,我想使用它而不是使用信号/插槽,因为在其他地方使用相同的代码概念不具备可移植性。 此外,我想继续检查子项,因为这段代码可能会在其他地方或对象中使用,而不仅仅是项目类型! 我写的只是我尝试做的事情的一个示例,但主要的JavaScript代码将在独立的js文件中。 我只需要知道一件事,QML是否真正支持完整的JavaScript语法。 - Creative Coder
@CreativeCoder,你找到解决方案了吗?我也想将一个函数作为参数传递给自定义对话框组件。很有趣,想知道你是如何解决的。提前感谢。 - Nulik

0

你可以添加一个属性到你的物品中,来保存回调函数的数组。

Item {
    id:self;
    property var visitFunCallbacks: []
}

在CreateObject()函数中,您可以使用箭头函数初始化此属性的数组(类似于这个代码 [() => console.log("嗨,我是从外部传递的回调!")])。

请查看此文档页面,希望它能帮助您。 https://doc.qt.io/qt-6/qtqml-javascript-dynamicobjectcreation.html


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接