QMLの値型とシーケンス参照

QML 値型と QML シーケンス型は必然的に値で渡されます。QML オブジェクト型とは対照的に、それ自身は ID を持たず、他のオブジェクトや値のプロパティとして、あるいはメソッドから返される値としてのみアクセスすることができます。このようなアクセスは暗黙のうちにコピーを生成します。しかし、JavaScriptではすべてがオブジェクトです。JavaScriptには値型という概念はありません。例えば、JavaScriptでfont.bold = true を実行した場合、font が何であろうと、fontbold プロパティがセットされることを期待します。しかし、次のコード・スニペットを考えてみよう:

import QtQuick
Text {
    onSomethingHappened: font.bold = true
}

この場合、font が値型であることがわかっています。この場合、bold が値型であることはわかっています。この値型にアクセスすると、Q_PROPERTY のゲッターを呼び出すことでローカルコピーが作成されます。その後、 プロパティを設定することができますが、通常はコピーにのみ影響し、元のQ_PROPERTY には影響しません。

この問題を解決するために、QMLには参照という概念があります。あるプロパティから値やシーケンス型のインスタンスを取得すると、 QMLエンジンは値そのものとともにそのプロパティを記憶します。値が変更されると、その値はプロパティに書き戻されます。これによって、あたかもオブジェクトが別個に存在しているかのような錯覚に陥り、上記のようなケースや他の多くのケースをうまく機能させることができるのです。

しかし、これはかなり高くつく可能性がある。シーケンスがQ_PROPERTY として公開されている場合、インデックスによってシーケンス内の任意の値にアクセスすると、シーケンスデータ全体がプロパティから読み込まれます。そして、このシーケンスデータから1つの要素を取得します。同様に、シーケンス内の任意の値を変更すると、シーケンスデータが読み込まれる。そして変更が実行され、変更されたシーケンスがプロパティに書き戻される。読み取り操作は、その型が暗黙的に共有されていれば比較的安価に行うことができます。変更は常に少なくとも1つのディープコピーを発生させます。

Q_INVOKABLE 関数からシーケンスや値型のインスタンスを返すと、このようなオーバーヘッドを避けることができます。戻り値はどのプロパティにもアタッチされず、書き戻されることもありません。

オブジェクト型のシーケンスは、デフォルトではQQmlListProperty として渡されます。QQmlListProperty は実際のコンテナではなく、シーケンシャルなストレージへのビュー(参照)にすぎません。したがって、QQmlListProperty はこの影響を受けない。しかし、QML_SEQUENTIAL_CONTAINER を使用して、オブジェクトに他のシーケンスタイプを登録することができます。それらは影響を受ける。

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.