Qt Protobuf QML タイプ
ジェネレータプラグインを使用すると、QMLにProtobufメッセージを登録できます。型を登録するには、QML およびQML_URI という生成キーを使用します。APIの詳細については、qt_add_protobuf()コマンドおよびAPI使用例「QML拡張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;
}User メッセージをQMLで公開するには、このprotobufスキーマと、QML 引数を指定したqt_add_protobuf()コマンドを使用します:
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メッセージ名を複数使用している場合、自動生成されたコード内で互いに矛盾する可能性があります。以下の例では、2つの異なるProtobufパッケージ(qtprotobufnamespace とqtprotobufnamespace1.nested )が、同じProtobufメッセージ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 メッセージを使用している場合、正しい動作は保証されず、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;
}上記のProtobufメッセージからQML型を生成するには、QML オプションを指定してqt_add_protobuf()マクロを使用してください。以下の例を参照してください:
qt_add_protobuf(example
PROTO_FILES
test.proto
QML
QML_URI
test.example
)QtQuick によるインポート後にprotobufメッセージをグローバルネームスペースにインポートすると、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)また、列挙型のフィールド名はアンダースコアで始まってはなりません。そのようなフィールドはそのまま生成されますが、将来的にQMLエンジンで登録が可能になるまでは、QML内では未定義となります。以下の*.proto の例を参照してください:
enum UnderScoreEnum {
_enumUnderscoreValue0 = 0;
_EnumUnderscoreValue1 = 1;
}生成された出力:
enum UnderScoreEnum {
_enumUnderscoreValue0 = 0,
_EnumUnderscoreValue1 = 1,
};
Q_ENUM(UnderScoreEnum)QMLのプロパティ構文に関する詳細については、「プロパティ属性の定義」を参照してください。
© 2026 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.