Qt Protobuf Types QML
Grâce au plugin générateur, 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. Consultez 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, à l’instar des types Q_GADGET intégrés. L’enregistrement s’effectue via le module QML.
Utilisation des messages Protobuf dans QML
Utilisez le plugin de génération pour générer des bibliothèques de messages Protobuf auxquelles vous pouvez accéder depuis des applications Qt Quick. L’API CMake d’Qt Protobuf dispose d’options spécifiques qui contrôlent la création du module QML.
Par exemple, vous disposez du 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érera une bibliothèque nommée userdb_gen, contenant les messages protobuf de userdb.proto avec prise en charge QML. Pour utiliser ces messages dans QML, importez le module QML généré à l'aide de 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 valeur QML. Pour les utiliser dans 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 callbacks 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 depuis QML. L’exemple ci-dessous montre comment créer un élément ComboBox à l’aide des valeurs de cette é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 aussi bien dans les propriétés que dans les méthodes invocables.
L’objet QML singleton ` 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 est de 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 depuis 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 messages Protobuf en double dans vos fichiers *.proto ou le faire avec prudence. Si votre application utilise plusieurs noms de messages Protobuf identiques déclarés dans différents paquets Protobuf, ceux-ci risquent d’entrer en conflit 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 en double dans différents modules QML et utilisez un <Qualifier> pour chaque importation de module QML, voir Importations de modules (espaces de noms). Voici un exemple montrant 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"
)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 noms en double déclenchera un avertissement lors de la compilation.
Duplicatas de types QML
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 pas être garanti et une erreur « Element is not creatable » sera générée. Pour éviter tout chevauchement des types QML, utilisez un <Qualifier> lors de l’importation des 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 s’ils étaient 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 un ` <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 réservés dans le contexte QML ou JavaScript, mais qui ne le sont pas dans le contexte *.proto. Les champs dont les noms sont réservés par QML seront étendus en silence par le suffixe « _proto » par le plugin générateur. Par exemple, id, property et import sont des mots-clés réservés. Ils seront remplacés par id_proto, property_proto et import_proto:
message MessageUpperCaseReserved {
sint32 Import = 1;
sint32 Property = 2;
sint32 Id = 3;
}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 ...)De plus, les valeurs d’énumération ne peuvent pas commencer par une lettre minuscule. Le plugin 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é :
enum LowerCaseEnum {
EnumValue0 = 0,
EnumValue1 = 1,
EnumValue2 = 2,
};
Q_ENUM(LowerCaseEnum)De plus, les champs d’énumération ne peuvent pas commencer par un trait de soulignement. Ces champs seront générés tels quels, mais seront non définis dans le QML, à moins que le moteur QML n’autorise leur enregistrement à l’avenir. Voir l’exemple *.proto ci-dessous :
enum UnderScoreEnum {
_enumUnderscoreValue0 = 0;
_EnumUnderscoreValue1 = 1;
}Code généré :
enum UnderScoreEnum {
_enumUnderscoreValue0 = 0,
_EnumUnderscoreValue1 = 1,
};
Q_ENUM(UnderScoreEnum)Pour plus d’informations sur la syntaxe des propriétés QML, consultez la section Définition des attributs de propriété.
© 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.