Qt Protobuf QML 유형
생성기 플러그인을 사용하면 QML에 프로토타입 메시지를 등록할 수 있습니다. 유형을 등록하려면 QML
및 QML_URI
생성 키를 사용합니다. API 세부 정보는 qt_add_protobuf 명령과 API 사용 예제 QML 확장 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에 노출하려면 QML
인수와 함께 protobuf 스키마와 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 함수는 QML을 지원하는 userdb.proto
의 protobuf 메시지를 포함하는 userdb_gen
라는 라이브러리를 생성합니다. QML에서 메시지를 사용하려면 qt_add_protobuf
호출의 QML_URI
인수에 지정된 URI를 사용하여 생성된 QML 모듈을 가져옵니다:
import userdb.pb
모든 protobuf 메시지는 QML 값 유형으로 등록됩니다. QML에서 사용하려면 일부 QML 항목에 대한 속성 속성을 정의하세요:
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 메시지 선언을 피하거나 현명하게 처리해야 합니다. 애플리케이션에서 서로 다른 프로토뷰 패키지 안에 선언된 여러 개의 동일한 프로토뷰 메시지 이름을 사용하는 경우 자동 생성된 코드에서 서로 모순될 수 있습니다. 아래 예시에서는 qtprotobufnamespace
와 qtprotobufnamespace1.nested
라는 두 개의 서로 다른 프로토 패키지가 동일한 프로토 메시지 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>를 사용하세요( 모듈(네임스페이스) 가져오기를 참조하세요). 아래 예제에서는 프로토버프 패키지를 다른 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; }
위의 프로토뷰 메시지에서 QML 유형을 생성하려면 QML
옵션과 함께 qt_add_protobuf 매크로를 사용하세요. 아래 예시를 참조하세요:
qt_add_protobuf(example PROTO_FILES test.proto QML QML_URI test.example )
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)
또한 열거형 필드는 밑줄 기호로 시작할 수 없습니다. 이러한 필드는 그대로 생성되지만 향후 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.