gpt4 book ai didi

qt - 如何制作从 QML 获取可变数量参数的 Q_INVOKABLE 方法

转载 作者:行者123 更新时间:2023-12-03 14:39:07 25 4
gpt4 key购买 nike

众所周知,在 JavaScript 中,所有函数都可以接受任意数量的参数。
在 Qt 中,您可以使用 Q_INVOKABLE 标记 QObject,其方法可从 QML 访问。例如:

class myObj: public QObject
{
Q_OBJECT

//...

public slots:
Q_INVOKABLE QJSValue myFunction(QJSValue value);

//...

};

然后你可以从 JS 调用它:
(function(){
//like this:
var result = myObj.myFunction("test");
//but also like this:
var result2 = myObj.myFunction(1,2,3,4,5); //,6,7,8, ..., 9998, 9999
})();

那么,如何在 C++ 端处理可变数量的参数?在 JS 方面,我们有“参数”对象。 Q_INVOKABLE 方法是否有任何类似物?

最佳答案

用正常的方法似乎是不可能做到的。现在我已经结束了解决方法。
QJSValue 可以包含任何 JS 类型。包括数组。所以方法看起来像这样:

QJSValue myObject::test(QJSValue arg1, QJSValue arg2, QJSValue rest)
{
qDebug() << "arg1 = " << arg1.toString();
qDebug() << "arg2 = " << arg2.toString();
auto args = toJSValueList(rest);
qDebug() << "args = [";
for(auto arg : args) {
qDebug() << " " << arg.toString() << ",";
}
qDebug() << "]";
return (arg1.isUndefined() ? 0 : 1) + (arg2.isUndefined() ? 0 : 1) + args.length();
}

参数 arg1 和 arg2 是必需的。其余参数可以作为第三个参数 - 数组传递给方法。方法 toJSValueList 只是将 QJSValue 包含的数组转换为 QJSValueList 的助手。
QJSValueList myObject::toJSValueList(QJSValue arg)
{
QJSValueList list;
auto length = arg.property("length");
if(length.isNumber()){
for(int i = 0, intLength = length.toInt(); i < intLength; ++i){
list << arg.property(static_cast<quint32>(i));
}
} else if(!arg.isUndefined()){
list << arg;
}
return list;
}

这足以使事情发挥作用。但是,如果有人确实需要将任意数量的参数直接传递给函数(而不是通过数组),则可以通过一些小技巧来完成。
class myObject: public QObject, public QmlSingletonProvider<QmlTimer>
{
Q_OBJECT
public:
//...
// declare property of type QJSValue which will actually be a function
Q_PROPERTY(QJSValue variadic_test READ variadic_test)

public slots:
Q_INVOKABLE QJSValue test(QJSValue arg1, QJSValue arg2, QJSValue rest);

private:
QJSValueList toJSValueList(QJSValue arg);
QJSValue variadic_test(); // getter for property
QJSValue variadic_test_fn; // stored JS function
};


// variadic wrapper for method test()
QJSValue myObject::variadic_test()
{
if(variadic_test_fn.isCallable())
return variadic_test_fn;

auto engine = qjsEngine(this);
if(!engine) return QJSValue();

variadic_test_fn = engine->evaluate("function(){ return this.test( arguments[0], arguments[1], Array.prototype.slice.call( arguments, 2 ) ); }");

return variadic_test_fn;
}

QJSValue 也可以是一个函数。因此,您可以添加类型为 QJSValue 的只读 Q_PROPERTY,并在第一次访问属性时为其分配 JS 函数。此函数将是一个包装器,它只是将其所有参数收集到数组并将其传递给您的实际方法。在 JS 中,您可以看到并调用这两个函数:实际函数和可变参数包装器。在示例中,我按原样传递了前两个参数(如果参数数量小于 2,则将传递“未定义”。),因为方法“测试”等待至少 2 个参数。其余参数通过“Array.prototype.slice.call(arguments, 2)”收集到一个数组中。如果您没有必需的参数,您可以使用“function(){ return this.test( Array.prototype.slice.call(arguments ) ); }”。
当然,您的 C++ 方法应该为可能的“未定义”值做好准备。并且需要手动检查每个参数的类型。它看起来更像是“JS 代码”,尽管它是用 C++ 编写的。

关于qt - 如何制作从 QML 获取可变数量参数的 Q_INVOKABLE 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52407560/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com