Qt Protobuf QMLタイプ
ジェネレータプラグインを使うと、QMLにprotobufメッセージを登録することができます。型を登録するには、QML
とQML_URI
の生成キーを使います。APIの詳細はqt_add_protobufコマンドとAPI使用例QML extended protobufを参照してください。
登録されたprotobufメッセージは、組み込みのQ_GADGET 型と同様にQMLで利用可能です。登録はQMLモジュールを介して行われます。
QMLでのprotobufメッセージの利用
ジェネレータプラグインを使用し、Qt Quick アプリケーションからアクセスできる protobuf メッセージのライブラリを生成してください。Qt Protobuf CMake APIには、QMLモジュールの作成を制御するそれぞれのオプションがあります。
例えば、User
メッセージを含むuserdb.proto
protobuf スキーマがあるとします:
syntax = "proto3"; package userdb; message User { enum Type { Admin = 0; Manager = 1; Account = 2; Director = 3; } Type type = 1; string name = 2; string email = 3; }
QML でUser
メッセージを公開するには、protobuf スキーマとqt_add_protobufコマンドにQML
引数を指定します:
qt_add_executable(appuserdb ... ) qt_add_qml_module(appuserdb URI userdb VERSION 1.0 QML_FILES ... SOURCES ... ) qt_add_protobuf(userdb_gen QML QML_URI "userdb.pb" PROTO_FILES userdb.proto ) target_link_libraries(appuserdb PRIVATE userdb_gen)
qt_add_protobuf関数はuserdb.proto
の protobuf メッセージを QML でサポートしたuserdb_gen
というライブラリを生成します。QML でメッセージを使用するには、qt_add_protobuf
のQML_URI
引数で指定された URI を使用して、生成された QML モジュールをインポートしてください:
import userdb.pb
すべてのprotobufメッセージはQMLの値型として登録されています。QMLでこれらを使用するには、QMLの項目にproperty属性を定義します:
Window { id: userAddForm property user newUser ... }
newUser
プロパティのtype
、name
、email
フィールドを変更するには、QML シグナルのコールバックを使用します。例えば
TextField { id: userNameField onTextChanged: { userAddForm.newUser.name = userNameField.text } } ... TextField { id: userEmailField onTextChanged: { userAddForm.newUser.email = userEmailField.text } }
User.Type
の列挙値も QML からアクセス可能です。以下の例では、この列挙値を用いてComboBox の項目を作成しています:
ComboBox { id: userTypeField textRole: "key" model: ListModel { id: userTypeModel ListElement { key: "Admin"; value: User.Admin } ListElement { key: "Second"; value: User.Manager } ListElement { key: "Account"; value: User.Account } ListElement { key: "Director"; value: User.Director } } onActivated: function(index) { userAddForm.newUser.type = userTypeModel.get(index).value } }
QMLとC++の統合
QML に登録された C++ クラスは、QML で作成されたメッセージを、プロパティと 呼び出し可能なメソッドの両方で使用することができます。
シングルトンの QML オブジェクトUserDBEngine
は、lastAddedUser
プロパティと呼び出し可能なメソッドaddUser
を QML に公開しています:
class UserDBEngine : public QObject { Q_OBJECT QML_ELEMENT QML_SINGLETON Q_PROPERTY(userdb::User lastAddedUser READ lastAddedUser WRITE setLastAddedUser NOTIFY lastAddedUserChanged FINAL) public: ... Q_INVOKABLE void addUser(const userdb::User &newUser); ... }
lastAddedUser
プロパティは、前節のuserdb.proto
スキーマから生成されたuserdb::User
型を持っています。呼び出し可能なaddUser
メソッドはuserdb::User
型のオブジェクトへの定数参照を受け付けます。プロパティもメソッドもQMLから使うことができます:
Button { text: "Add" onClicked: { // Use the property created in the previous section UserDBEngine.addUser(userAddForm.newUser) } } ... Text { // The text will be updated automatically when lastAddedUser is changed text: "Last added user: " + UserDBEngine.lastAddedUser.name }
Protobufメッセージの重複
*.proto
、protobufメッセージの重複宣言を避けるか、あるいは賢明に行 うべきです。異なるprotobufパッケージの中で宣言された同じprotobufメッセー ジ名を複数使用すると、自動生成されるコードの中で矛盾が生じる可能性があります。以下の例では、qtprotobufnamespace
とqtprotobufnamespace1.nested
という 2 つの異なる proto パッケージが、同じ proto メッセージNestedFieldMessage
を使用しています。ファイルnested.proto
:
syntax = "proto3"; package qtprotobufnamespace; import "externalpackage.proto"; message NestedFieldMessage { sint32 testFieldInt = 1; }
ファイルnestedspace1.proto
:
syntax = "proto3"; package qtprotobufnamespace1.nested; message NestedFieldMessage { message NestedMessage { sint32 field = 1; } NestedMessage nested = 1; }
パッケージ間の名前の重複を避けることができない場合は、重複するメッセージを異なるQMLモジュールに置き、各QMLモジュールのインポートに<Qualifier>を使用します(モジュール(名前空間)のインポートを参照)。以下に、protobufパッケージを異なるQMLモジュールに追加する例を示します:
# qtprotobufnamespace QML module qt_add_protobuf(nestedtypes_qtprotobuf_qml PROTO_FILES nested.proto QML QML_URI qtprotobufnamespace OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/qt_protobuf_gen1" ) ... # qtprotobufnamespace1.nested QML module qt_add_protobuf(nestedspace_qml PROTO_FILES nestedspace1.proto QML QML_URI qtprotobufnamespace1.nested OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/qt_protobuf_gen2" )
<Qualifier>の使用例:
import qtprotobufnamespace as NestedFieldMessages import qtprotobufnamespace1.nested as FieldMessages_Nested1 ... property NestedFieldMessages.nestedFieldMessage fieldMsg1; property FieldMessages_Nested1.nestedFieldMessage fieldMsg2;
注意: 重複して使用するとコンパイル時に警告が表示されます。
QML型の重複
QMLですでに予約されている名前のprotobufメッセージをQML型として使用する場合、正しい動作が保証されず、Element is not creatable
。QML型の重複を防ぐためには、QMLモジュールのインポートに<Qualifier>を使用してください。例えば、以下のprotobufメッセージは、グローバル名前空間にインポートした場合、Text やItem のQMLタイプと衝突してしまいます:
syntax = "proto3"; package test.example; message Text { string text = 1; } message Item { sint32 width = 1; sint32 height = 2; }
qt_add_protobufマクロにQML
オプションをつけて、上記の protobuf メッセージから QML タイプを生成できるようにしてください。以下の例を参照してください:
qt_add_protobuf(example PROTO_FILES test.proto QML QML_URI test.example )
protobufメッセージがQtQuick インポート後にグローバル名前空間にインポートされた場合、QML型との衝突が発生します。以下の例を参照してください:
import QtQuick import test.example Item { id: root ... property ProtobufMessages.item itemData }
QML 型との衝突を避けるには、<Qualifier>
を使用して、生成された QML モジュールをローカル名前空間にインポートしてください。以下の例を参照してください:
// No qualifier - global namespace import QtQuick // ProtobufMessages - a qualifier of local namespace. import test.example as ProtobufMessages Item { id: root ... property ProtobufMessages.item itemData }
QMLキーワードの取り扱い
QML や JavaScript では予約されているが、*.proto では予約されていないキーワードに 注意してください。QMLで予約されている名前のフィールドは、ジェネレータプラグインによって、_proto
というサフィックスによって無言で拡張されます。例えば、id
、property
、import
は予約されたキーワードです。これらはid_proto
,property_proto
,import_proto
で置き換えられます:
message MessageUpperCaseReserved { sint32 Import = 1; sint32 Property = 2; sint32 Id = 3; }
生成されたコード出力:
Q_PROPERTY(QtProtobuf::sint32 import_proto READ import_proto ...) Q_PROPERTY(QtProtobuf::sint32 property_proto READ property_proto ...) Q_PROPERTY(QtProtobuf::sint32 id_proto READ id_proto ...)
また、列挙値は小文字で始めることはできません。ジェネレーター・プラグインは、コード出力の最初の文字を大文字にします。以下の*.proto
の例を参照してください:
enum LowerCaseEnum { enumValue0 = 0; enumValue1 = 1; enumValue2 = 2; }
生成されたコード出力:
enum LowerCaseEnum { EnumValue0 = 0, EnumValue1 = 1, EnumValue2 = 2, }; Q_ENUM(LowerCaseEnum)
また、enum フィールドはアンダースコア記号で始めることはできません。このようなフィールドはそのまま生成されますが、将来QMLエンジンがこのようなフィールドの登録を許可しない限り、QMLの中では未定義となります。以下の*.proto
の例を参照してください:
enum UnderScoreEnum { _enumUnderscoreValue0 = 0; _EnumUnderscoreValue1 = 1; }
生成された出力:
enum UnderScoreEnum { _enumUnderscoreValue0 = 0, _EnumUnderscoreValue1 = 1, }; Q_ENUM(UnderScoreEnum)
QML プロパティの構文についての詳細は、「プロパティ属性の定義」を参照してください。
© 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.