简体   繁体   English

如何将数据从QML传递到C ++作为可变引用

[英]How to pass data from QML to C++ as a mutable reference

I have a Q_INVOKABLE method in C++ class and I want this method to return data back to QML, within the same method, without the use of signals. 我在C ++类中有一个Q_INVOKABLE方法,我希望这个方法在相同的方法中将数据返回到QML,而不使用信号。

My mehtod is declared as: 我的mehtod被宣布为:

Q_INVOKABLE void select_company(int index,QString *out);

And defined as: 并定义为:

void Companies::select_company(int index,QString *out) {

    out->clear();
    out->append("out string");
}

When I call it from a JavaScript function in QML: 当我从QML中的JavaScript函数调用它时:

var out_str;
data_model.select_company(index,out_str);
console.log(out_str);

I get this output on the console: 我在控制台上获得此输出:

qrc:/CompaniesList.qml:56: Error: Unknown method parameter type: QString*

Is it possible to pass a (JavaScript) variable from QML to C++ method, and have C++ to modify this variable ? 是否可以将(JavaScript)变量从QML传递给C ++方法,并使用C ++来修改此变量? If it is not possible to do that by passing a pointer or reference, what is the (simplest) other approach to do this? 如果通过传递指针或引用无法做到这一点,那么(最简单的)其他方法是做什么的?

The only way I have found so far is by passing a QJSValue and set properties to it, like this: 到目前为止我找到的唯一方法是传递一个QJSValue并设置属性,如下所示:

Declaration: 宣言:

Q_INVOKABLE void select_company(int index,QJSValue out);

Definition: 定义:

void Companies::select_company(int index,QJSValue out) {

    out.setProperty("company_name","Acme, Inc.");
    out.setProperty("identity_id",29673);
}

QML: QML:

var retval={};
data_model.select_company(index,retval);
console.log(retval.company_name);
console.log(retval.identity_id);

Would be interesting to find out all the possible ways to call a C++ method and return some data immediately. 有趣的是找出所有可能的方法来调用C ++方法并立即返回一些数据。

If you want to "pass by reference" and edit a JavaScript object on the C++ side, then QJSValue is the way to go. 如果你想“通过引用传递”并在C ++端编辑JavaScript对象,那么QJSValue就是你要走的路。 There is no direct support for C++ types out of the box, there are some conversions for specific types. 开箱即用的C ++类型没有直接支持,特定类型有一些转换。

Passing as a pointer will only work for QObject derived objects. 作为指针传递仅适用于QObject派生对象。

Keep in mind that QJSValue will work only if it is an Object , maybe also an array. 请记住, QJSValue只有在它是一个Object时才有效,也可能是一个数组。 It will not work for other types, as the object will be copied, and changes will be done on the copy and will not be reflected on the original object. 它不适用于其他类型,因为将复制对象,并且将在副本上进行更改,并且不会在原始对象上反映。

Not that I mind, but what stops you from declaring something like: 不是我在想,但是什么阻止你宣布:

Q_INVOKABLE QString getSomeValueFromCPP(int index) {
 ...
 return value; 
}

and then in QML: 然后在QML中:

var val = getSomeValueFromCPP(index);

For more complicated structures if you need to return something by-value I suggest to have a look on Q_GADGET approach, it's awesome. 对于更复杂的结构,如果你需要按值返回一些东西,我建议看一下Q_GADGET方法,它真棒。

PS as there are so many comments I decided to make a small update in here rather then in comments. PS因为有很多评论我决定在这里做一个小的更新,而不是在评论中。

First of all, I want to give a credits to all ddriver comments as they are all completely right. 首先,我想给所有ddriver评论一个学分,因为它们都是完全正确的。

It's absolutely true that first thing to do is to review a design, as any QML/C++ interactions are not really consider such approach as mentioned in the initial question. 首先要做的是审查设计,因为任何QML / C ++交互都不是真正考虑初始问题中提到的这种方法。 Second is that it's very important to make a distinguish between ownership for QObject based classes and passed-by-value instances. 其次,区分基于QObject的类和按值传递的实例的所有权非常重要。 In case you are going to use a QObject based classed (doesn't matter QML or C++ ownership) you should clearly decide who's going to be a creator of these objects. 如果您打算使用基于QObject的分类(无论QML或C ++所有权),您应该明确决定谁将成为这些对象的创建者。 Also pay attention that any QObjects created in C++ code without an explicit parent and passed into QML engine will be destroyed at some point by garbage collector. 还要注意,在没有显式父代的情况下在C ++代码中创建并传递到QML引擎的任何QObject都将在某些时候被垃圾收集器破坏。 Thats very flexible and powerful approach allows to create very efficient data structures like QObject-based models with full properties support etc. 这种非常灵活和强大的方法允许创建非常有效的数据结构,如基于QObject的模型,具有完整的属性支持等。

To avoid complications Qt provides another way of dealing with structured data in case you need just to pass values into QML from C++ (as I understand a question that's what you are trying to achieve). 为了避免复杂化,Qt提供了另一种处理结构化数据的方法,以防您只需要将值从C ++传递到QML中(因为我理解的是您正在尝试实现的问题)。 That's Q_GADGETS. 这是Q_GADGETS。 Thats a similar to Q_OBJECT way of attaching metadata to structures allowing them to have a Q_PROPERTIES, full MetaType information (so qobject_cast will work for example, as well as any QVariant transformations), but excluding SLOTS/SIGNALS. 这类似于将元数据附加到结构的Q_OBJECT方式,允许它们具有Q_PROPERTIES,完整的MetaType信息(例如qobject_cast将起作用,以及任何QVariant转换),但不包括SLOTS / SIGNALS。

Major difference is that you are allowed to make a pass-by-value invocations, where you should't bother (to some point) about ownership as well as live-cycle. 主要区别在于您可以进行按值传递调用,您不应该(在某些方面)对所有权和实时循环感到烦恼。 In simple words in case of Q_GADGET return type QML will get a COPY of initial object and will destroy it then it's not needed. 简单来说,在Q_GADGET返回类型的情况下,QML将获得初始对象的COPY并将其销毁,然后不需要它。

As mentioned in ddriver answer it's possible to simulate reference parameter then calling C++ method from QML, but I have my doubts it's right way to go as from my point of view it's lack in design. 正如在ddriver中提到的那样,可以模拟参考参数然后从QML调用C ++方法,但我怀疑它是正确的方式,从我的观点来看,它缺乏设计。

In your question you are asking about certain technique, but point is that - proper answer is to review a design as what you are trying to do is not how it's supposed to work. 在你的问题中,你问的是某种技术,但重点是 - 正确的答案是审查一个设计,因为你想要做的不是它应该如何工作。 Again as ddriver mentioned you should look on C++ part as on "core" providing data in certain way - it can be QObject based models/standalone objects or value-based instances based on Q_GADGET, while QML part is a "representation" logic, it shouldn't be used to create/hold something which C++ suppose to modify, especially by reference. 同样,正如ddriver所提到的那样,你应该把C ++部分看作是以某种方式提供数据的“核心” - 它可以是基于QObject的模型/独立对象或基于Q_GADGET的基于值的实例,而QML部分是一个“表示”逻辑,它不应该用来创建/保存C ++想要修改的东西,特别是通过引用。

Ragaring Nulik comments - typical use case is to return Q_GADGET based classes into QML from C++. Ragaring Nulik评论 - 典型的用例是将基于Q_GADGET的类从C ++ 返回到QML。 You shouldn't try to pass those values by reference for modifications inside C++ code. 您不应该尝试通过引用传递这些值以进行C ++代码中的修改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM