Qt Protobuf Tipos QML
Con el plugin generador, puedes registrar mensajes protobuf en el QML. Para registrar el tipo, utilice las claves de generación QML y QML_URI. Consulte los detalles de la API en el comando qt_add_protobuf y el ejemplo de uso de la API QML extended protobuf.
Los mensajes protobuf registrados están disponibles en QML, al igual que los tipos incorporados de Q_GADGET. El registro se realiza a través del módulo QML.
Uso de mensajes protobuf en QML
Utiliza el plugin generador para generar librerías de mensajes protobuf a las que puedas acceder desde aplicaciones Qt Quick. La API CMake deQt Protobuf tiene las respectivas opciones que controlan la creación del módulo QML.
Por ejemplo, tienes el esquema protobuf userdb.proto que contiene el mensaje 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;
}Para exponer el mensaje User en QML, utilice el esquema protobuf y el comando qt_add_protobuf con el argumento 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 función qt_add_protobuf generará una biblioteca llamada userdb_gen, que contendrá los mensajes protobuf de userdb.proto con soporte QML. Para utilizar los mensajes en QML, importe el módulo QML generado utilizando el URI especificado en el argumento QML_URI de la llamada qt_add_protobuf:
import userdb.pbTodos los mensajes protobuf están registrados como tipos de valor QML. Para utilizarlos en QML, defina el atributo property para algún elemento QML:
Window {
id: userAddForm
property user newUser
...
}Para cambiar los campos type, name, o email de la propiedad newUser, utilice las retrollamadas de señal QML. Por ejemplo:
TextField {
id: userNameField
onTextChanged: {
userAddForm.newUser.name = userNameField.text
}
}
...
TextField {
id: userEmailField
onTextChanged: {
userAddForm.newUser.email = userEmailField.text
}
}Los valores del enum User.Type también son accesibles desde QML. El siguiente ejemplo muestra cómo crear un elemento ComboBox utilizando los valores del enum:
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
}
}Integración de QML y C
Las clases C++ registradas en QML pueden utilizar los mensajes creados en QML tanto en propiedades como en métodos invocables.
El objeto QML singleton UserDBEngine expone a QML la propiedad lastAddedUser y el método invocable addUser:
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 propiedad lastAddedUser tiene el tipo userdb::User generado a partir del esquema userdb.proto de la sección anterior. El método invocable addUser acepta una referencia constante a un objeto de tipo userdb::User. Tanto la propiedad como el método pueden utilizarse desde 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
}Duplicados de mensajes protobuf
Debe evitar la declaración de duplicados de mensajes protobuf en sus archivos *.proto o hacerlo con prudencia. Si tu aplicación utiliza varios nombres de mensajes protobuf idénticos declarados dentro de diferentes paquetes protobuf, podrían contradecirse en el código autogenerado. En el siguiente ejemplo, dos paquetes proto diferentes, qtprotobufnamespace y qtprotobufnamespace1.nested, utilizan el mismo mensaje proto NestedFieldMessage. El archivo nested.proto:
syntax = "proto3";
package qtprotobufnamespace;
import "externalpackage.proto";
message NestedFieldMessage {
sint32 testFieldInt = 1;
}El archivo nestedspace1.proto:
syntax = "proto3";
package qtprotobufnamespace1.nested;
message NestedFieldMessage {
message NestedMessage {
sint32 field = 1;
}
NestedMessage nested = 1;
}En caso de que no haya posibilidad de evitar duplicados de nombres entre paquetes, entonces ponga los mensajes duplicados en diferentes módulos QML y use un <Qualifier> para cada importación de módulo QML, vea Importaciones de Módulo (Namespace). A continuación el ejemplo de cómo añadir paquetes protobuf en diferentes módulos 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"
)El ejemplo de uso de <Qualifier>:
import qtprotobufnamespace as NestedFieldMessages import qtprotobufnamespace1.nested as FieldMessages_Nested1 ... property NestedFieldMessages.nestedFieldMessage fieldMsg1; property FieldMessages_Nested1.nestedFieldMessage fieldMsg2;
Nota: El uso de duplicados provocará una advertencia en tiempo de compilación.
Tipos QML duplicados
Si su aplicación utiliza mensajes protobuf con nombres que ya están reservados en QML como tipos QML, no se puede garantizar el comportamiento correcto y se activaría el error Element is not creatable. Para evitar una superposición de tipos QML, utilice un <Qualifier> para la importación de módulos QML, consulte Importaciones de módulos (espacios de nombres). Por ejemplo, los siguientes mensajes protobuf se solaparían con los tipos QML Text y Item al importarlos al espacio de nombres global:
syntax = "proto3";
package test.example;
message Text {
string text = 1;
}
message Item {
sint32 width = 1;
sint32 height = 2;
}Utilice la macro qt_add_protobuf con la opción QML para permitir la generación de tipos QML a partir de los mensajes protobuf anteriores. Véase el ejemplo siguiente:
qt_add_protobuf(example
PROTO_FILES
test.proto
QML
QML_URI
test.example
)Se producirán conflictos con los tipos QML si los mensajes protobuf se importan a un espacio de nombres global después de la importación de QtQuick. Véase el ejemplo siguiente:
import QtQuick
import test.example
Item {
id: root
...
property ProtobufMessages.item itemData
}Para evitar conflictos con los tipos QML, utilice <Qualifier> para importar el módulo QML generado a un espacio de nombres local. Véase el ejemplo siguiente:
// No qualifier - global namespace
import QtQuick
// ProtobufMessages - a qualifier of local namespace.
import test.example as ProtobufMessages
Item {
id: root
...
property ProtobufMessages.item itemData
}Manejo de palabras clave QML
Preste atención a las palabras clave que están reservadas en el contexto QML o JavaScript, pero no reservadas en el contexto *.proto. Los campos con nombres reservados por QML serán extendidos silenciosamente por el sufijo _proto por el plugin generador. Por ejemplo, id, property, y import son palabras clave reservadas. Se sustituirán por id_proto, property_proto, import_proto:
message MessageUpperCaseReserved {
sint32 Import = 1;
sint32 Property = 2;
sint32 Id = 3;
}Salida de código generado:
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 ...)
Además, los valores enum no pueden comenzar con una letra minúscula. El plugin generador pondrá en mayúscula la primera letra en la salida de código. Véase el ejemplo *.proto más abajo:
enum LowerCaseEnum {
enumValue0 = 0;
enumValue1 = 1;
enumValue2 = 2;
}Código generado:
enum LowerCaseEnum { EnumValue0 = 0, EnumValue1 = 1, EnumValue2 = 2, }; Q_ENUM(LowerCaseEnum)
Además, los campos enum no pueden comenzar con un guión bajo. Tales campos se generarán tal cual, pero no se definirán en el QML, a menos que el motor QML permita registrarlos en el futuro. Véase el ejemplo *.proto más abajo:
enum UnderScoreEnum {
_enumUnderscoreValue0 = 0;
_EnumUnderscoreValue1 = 1;
}Salida generada:
enum UnderScoreEnum { _enumUnderscoreValue0 = 0, _EnumUnderscoreValue1 = 1, }; Q_ENUM(UnderScoreEnum)
Para obtener más información sobre la sintaxis de las propiedades QML, consulte Definición de atributos de propiedades.
© 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.