Qt Protobuf Types QML
Avec le plugin generator, vous pouvez enregistrer des messages protobuf dans le QML. Pour enregistrer le type, utilisez les clés de génération QML et QML_URI. Voir les détails de l'API dans la commande qt_add_protobuf et l'exemple d'utilisation de l'API QML extended protobuf.
Les messages protobuf enregistrés sont disponibles dans le QML, comme les types intégrés dans Q_GADGET. L'enregistrement se fait via le module QML.
Utilisation des messages protobuf dans QML
Utilisez le plugin generator pour générer des bibliothèques de messages protobuf auxquelles vous pouvez accéder à partir des applications Qt Quick. L'API CMake deQt Protobuf dispose d'options respectives qui contrôlent la création du module QML.
Par exemple, vous avez le schéma protobuf userdb.proto qui contient le message User:
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;
}Pour exposer le message User en QML, utilisez le schéma protobuf et la commande qt_add_protobuf avec l'argument 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)La fonction qt_add_protobuf génère une bibliothèque appelée userdb_gen, qui contient les messages protobuf de userdb.proto avec le support QML. Pour utiliser les messages en QML, importez le module QML généré en utilisant l'URI spécifié dans l'argument QML_URI de l'appel qt_add_protobuf:
import userdb.pbTous les messages protobuf sont enregistrés en tant que types de valeurs QML. Pour les utiliser en QML, définissez l'attribut property pour un élément QML :
Window {
id: userAddForm
property user newUser
...
}Pour modifier les champs type, name ou email de la propriété newUser, utilisez les rappels de signaux QML. Par exemple :
TextField {
id: userNameField
onTextChanged: {
userAddForm.newUser.name = userNameField.text
}
}
...
TextField {
id: userEmailField
onTextChanged: {
userAddForm.newUser.email = userEmailField.text
}
}Les valeurs de l'énumération User.Type sont également accessibles à partir de QML. L'exemple ci-dessous montre comment créer un élément ComboBox à l'aide des valeurs de l'énumération :
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
}
}Intégration de QML et de C++
Les classes C++ enregistrées dans QML peuvent utiliser les messages créés dans QML à la fois dans les propriétés et dans les méthodes invocables.
L'objet singleton QML UserDBEngine expose la propriété lastAddedUser et la méthode invocable 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); ... }
La propriété lastAddedUser a le type userdb::User généré à partir du schéma userdb.proto de la section précédente. La méthode invocable addUser accepte une référence constante à un objet de type userdb::User. La propriété et la méthode peuvent toutes deux être utilisées à partir de 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
}Duplicatas de messages protobuf
Vous devez éviter de déclarer des doublons de messages protobuf dans vos fichiers *.proto ou le faire avec discernement. Si votre application utilise plusieurs noms de messages protobuf identiques déclarés dans différents paquets protobuf, ils risquent de se contredire dans le code généré automatiquement. Dans l'exemple ci-dessous, deux paquets protobuf différents, qtprotobufnamespace et qtprotobufnamespace1.nested, utilisent le même message protobuf NestedFieldMessage. Le fichier nested.proto:
syntax = "proto3";
package qtprotobufnamespace;
import "externalpackage.proto";
message NestedFieldMessage {
sint32 testFieldInt = 1;
}Le fichier nestedspace1.proto:
syntax = "proto3";
package qtprotobufnamespace1.nested;
message NestedFieldMessage {
message NestedMessage {
sint32 field = 1;
}
NestedMessage nested = 1;
}S'il n'est pas possible d'éviter les doublons de noms entre les paquets, placez les messages dupliqués dans différents modules QML et utilisez un <Qualifier> pour chaque importation de module QML, voir Module (Namespace) Imports. L'exemple ci-dessous montre comment ajouter des paquets protobuf dans différents modules 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"
)L'exemple d'utilisation de <Qualifier> :
import qtprotobufnamespace as NestedFieldMessages import qtprotobufnamespace1.nested as FieldMessages_Nested1 ... property NestedFieldMessages.nestedFieldMessage fieldMsg1; property FieldMessages_Nested1.nestedFieldMessage fieldMsg2;
Remarque : l'utilisation de doublons déclenche un avertissement au moment de la compilation.
Types QML dupliqués
Si votre application utilise des messages protobuf dont les noms sont déjà réservés dans QML en tant que types QML, le comportement correct ne peut être garanti et l'erreur Element is not creatable sera déclenchée. Pour éviter un chevauchement des types QML, utilisez un <Qualifier> pour l'importation de modules QML, voir Importations de modules (espaces de noms). Par exemple, les messages protobuf suivants entreraient en conflit avec les types QML Text et Item lorsqu'ils sont importés dans l'espace de noms global :
syntax = "proto3";
package test.example;
message Text {
string text = 1;
}
message Item {
sint32 width = 1;
sint32 height = 2;
}Utilisez la macro qt_add_protobuf avec l'option QML pour activer la génération de types QML à partir des messages protobuf ci-dessus. Voir l'exemple ci-dessous :
qt_add_protobuf(example
PROTO_FILES
test.proto
QML
QML_URI
test.example
)Des conflits avec les types QML se produiront si les messages protobuf sont importés dans un espace de noms global après l'importation de QtQuick. Voir l'exemple ci-dessous :
import QtQuick
import test.example
Item {
id: root
...
property ProtobufMessages.item itemData
}Pour éviter les conflits avec les types QML, utilisez une adresse <Qualifier> pour importer le module QML généré dans un espace de noms local. Voir l'exemple ci-dessous :
// No qualifier - global namespace
import QtQuick
// ProtobufMessages - a qualifier of local namespace.
import test.example as ProtobufMessages
Item {
id: root
...
property ProtobufMessages.item itemData
}Gestion des mots-clés QML
Faites attention aux mots-clés qui sont réservés dans le contexte QML ou JavaScript, mais qui ne sont pas réservés dans le contexte *.proto. Les champs dont les noms sont réservés par QML seront silencieusement étendus par le suffixe _proto par le plugin de génération. Par exemple, id, property, et import sont des mots-clés réservés. Ils seront remplacés par id_proto, property_proto, import_proto:
message MessageUpperCaseReserved {
sint32 Import = 1;
sint32 Property = 2;
sint32 Id = 3;
}Sortie du code généré :
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 ...)
En outre, les valeurs d'énumération ne peuvent pas commencer par une lettre minuscule. Le plugin du générateur mettra la première lettre en majuscule dans le code généré. Voir l'exemple *.proto ci-dessous :
enum LowerCaseEnum {
enumValue0 = 0;
enumValue1 = 1;
enumValue2 = 2;
}Code généré en sortie :
enum LowerCaseEnum { EnumValue0 = 0, EnumValue1 = 1, EnumValue2 = 2, }; Q_ENUM(LowerCaseEnum)
De même, les champs enum ne peuvent pas commencer par un symbole de soulignement. Ces champs seront générés tels quels, mais ne seront pas définis dans le QML, à moins que le moteur QML ne permette de les enregistrer à l'avenir. Voir l'exemple *.proto ci-dessous :
enum UnderScoreEnum {
_enumUnderscoreValue0 = 0;
_EnumUnderscoreValue1 = 1;
}Sortie générée :
enum UnderScoreEnum { _enumUnderscoreValue0 = 0, _EnumUnderscoreValue1 = 1, }; Q_ENUM(UnderScoreEnum)
Pour plus d'informations sur la syntaxe des propriétés QML, voir Définir les attributs des propriétés.
© 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.