2016-12-30 50 views
3

私はQ_INVOKABLEメソッドをC++クラスに持っています。このメソッドは、信号を使用せずに同じメソッド内でQMLにデータを返すようにします。QMLからC++へのデータを変更可能な参照として渡す方法

私mehtodは次のように宣言され

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

のように定義:私はこの出力を得る

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

:私はQMLでJavaScript関数からそれを呼び出す

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

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

コンソールの場合:

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

(JavaScript)変数をQMLからC++メソッドに渡してC++にこの変数を変更させることはできますか?ポインタや参照を渡すことでそれを行うことができない場合は、これを行うための(最も単純な)他のアプローチは何ですか?

私がこれまでに発見した唯一の方法は、このように、それにQJSValueと設定されたプロパティを渡すことです:

宣言:

Q_INVOKABLE void select_company(int index,QJSValue out); 

定義:

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

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

QML:

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

C++メソッドを呼び出してすぐにデータを返すすべての可能な方法を見つけるのは興味深いでしょう。

+1

http://stackoverflow.com/questions/31618468/passing-a-javascript-callback-to-ac-invoked-method-in-qml – AlexanderVX

+0

@AlexanderVX、そのコードには妥当性検証がありません。 jsCallback.isCallable()が呼び出された後でなければ、jsCallback.isCallable()をチェックしてください。しかし、私は関数を宣言したくないので、QtがC++側でJavaScriptの値を変更できるようにします。 – Nulik

答えて

1

"参照渡し"でJavaScriptオブジェクトをC++側で編集する場合は、QJSValueが最適です。 C++型の直接サポートはありません。特定の型の変換がいくつかあります。

ポインタとして渡すと、派生オブジェクトのQObjectにしか作用しません。

QJSValueObject(多分配列も可能)の場合にのみ機能します。オブジェクトがコピーされ、コピーで変更が行われ、元のオブジェクトには反映されないため、他のタイプでは機能しません。

+0

それはアプローチがうまくいく、個人的に私が気に入っていないことは、C++のすべてのメソッドがすべて同じ型パラメータで非常に抽象的なので、読みにくく、間違いやすい間違いなく動作し、時には助けます。) – evilruff

1

は、私は気にしないということが、何のような何かを宣言からあなたを停止します。QMLで、その後

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

をして:

var val = getSomeValueFromCPP(index); 

より複雑な構造のためにあなたは値によって何かを返す必要がある場合私はQ_GADGETのアプローチを見てみることをお勧めします、それは素晴らしいです。

P.S.非常に多くのコメントがあるので、コメントではなくここで小さな更新を行うことにしました。

まず、すべてのddriverコメントにすべてクレジットを付したいと思います。

最初のことは、どのようなQML/C++のやりとりも実際には最初の質問で述べたようなアプローチを考慮していないため、設計を見直すことです。次に、QObjectベースのクラスと値渡しのインスタンスの所有権を区別することは非常に重要です。 QObjectベースのクラスを使用する場合(QMLまたはC++の所有権に関係なく)、これらのオブジェクトの作成者になる人を明確に決定する必要があります。また、明示的な親なしでQMLエンジンに渡されたC++コードで作成されたQObjectは、ある時点でガベージコレクタによって破棄されることに注意してください。 QtはあなただけQMLに値を渡す必要がある場合、構造化データを扱うための別の方法を提供し、合併症を避けるために非常に柔軟で強力なアプローチは、完全な性質ではQObjectベースのモデルのような非常に効率的なデータ構造を作成することができますザッツサポートなど

C++から(あなたが達成しようとしていることを私が理解しているので)それはQ_GADGETSです。これは、構造にメタデータを付加するQ_OBJECT方法と同様に、Q_PROPERTIES、完全なMetaType情報を持つことができます(qobject_castはたとえばQVariant変換と同様に動作します)。ただし、SLOTS/SIGNALSは除きます。

主な相違点は、値渡しの呼び出しを許可することです。ここでは、所有権とライブサイクルを気にする必要はありません。 Q_GADGETの戻り値の場合、QMLは初期オブジェクトのCOPYを取得し、それを破壊します。それは必要ありません。

ddriverの回答で述べたように、参照パラメータをシミュレートしてからQMLからC++メソッドを呼び出すことは可能ですが、私の疑問を抱いています。

あなたの質問では、特定のテクニックについて尋ねていますが、適切な答えは、あなたがしようとしていることがどのように動作するのかということではなく、デザインを見直すことです。ここでもddriverが述べたように、C++の部分は、QMLベースのモデル/スタンドアロンオブジェクトやQ_GADGETに基づくバリューベースのインスタンスとすることができ、QMLパーツは「表現」ロジックです。 C++が修正すると思われるもの、特に参照するものを作成/保持するために使うべきではありません。

Ragaring Nulikコメント - 典型的な使用例はreturn Q_GADGETをC++のQMLに基づいています。 C++コード内の変更については、これらの値を参照渡しで渡すべきではありません。

+0

ここでの考え方は、元のパラメータオブジェクトをC++から変更することです。 – dtech

+0

Q_INVOKABLE QString getNewVal(index、oldVal);それはどちらかの値(私は最もクリーンな方法と思う)またはQObjectとプロパティの変更..古い値を上書きするため、戻り値の型を使用しない点が表示されません。 – evilruff

+0

いくつかのパラメータを変更したい場合はどうすればよいですか?複数の値を返すことはできません。 – dtech

関連する問題