QML 문서의 구조

QML 문서는 세 부분으로 구성된 독립된 QML 소스 코드 조각입니다:

  • 선택적 프래그마 목록
  • 임포트
  • 단일 루트 객체 선언

관례에 따라 하나의 빈 줄로 임포트를 객체 계층 구조 정의에서 분리합니다.

QML 문서는 항상 UTF-8 형식으로 인코딩됩니다.

프라그마

프라그마는 현재 파일에 있는 객체의 특정 특성을 지정하거나 엔진이 코드를 해석하는 방식을 수정하는 데 사용할 수 있는 QML 엔진 자체에 대한 지침입니다. 다음 프래그마는 아래에 자세히 설명되어 있습니다.

  • Singleton
  • ListPropertyAssignBehavior
  • ComponentBehavior
  • FunctionSignatureBehavior
  • NativeMethodBehavior
  • ValueTypeBehavior
  • Translator

싱글톤

pragma Singleton QML 문서에 정의된 컴포넌트를 싱글톤으로 선언합니다. 싱글톤은 QML 엔진당 한 번만 생성됩니다. QML로 선언된 싱글톤을 사용하려면 해당 모듈에도 싱글톤을 등록해야 합니다. CMake로 이 작업을 수행하는 방법은 qt_target_qml_sources를 참조하십시오.

ListPropertyAssignBehavior

이 프라그마를 사용하면 QML 문서에 정의된 컴포넌트에서 목록 속성에 대한 할당이 처리되는 방식을 정의할 수 있습니다. 기본적으로 목록 프로퍼티에 할당하면 목록에 추가됩니다. Append 값을 사용하여 이 동작을 명시적으로 요청할 수 있습니다. 또는 Replace 을 사용하여 목록 속성의 내용을 항상 대체하도록 요청하거나 ReplaceIfNotDefault 을 사용하여 기본 속성이 아닌 경우 대체하도록 요청할 수 있습니다. 예를 들어

pragma ListPropertyAssignBehavior: ReplaceIfNotDefault

참고: 클래스 선언에 QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_APPEND, QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_REPLACE, QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_REPLACE_IF_NOT_DEFAULT 매크로를 추가하여 C++ 정의 유형에 대해서도 동일한 선언을 지정할 수 있습니다.

컴포넌트 비헤이비어

동일한 QML 파일에 여러 컴포넌트가 정의되어 있을 수 있습니다. QML 파일의 루트 범위는 컴포넌트이며, 명시적 또는 암시적으로 프로퍼티로 생성된 QQmlComponent 유형의 요소 또는 인라인 컴포넌트를 추가로 가질 수 있습니다. 이러한 컴포넌트는 중첩됩니다. 각 내부 컴포넌트는 하나의 특정 외부 컴포넌트 안에 있습니다. 대부분의 경우 외부 컴포넌트에 정의된 ID는 중첩된 모든 내부 컴포넌트 내에서 액세스할 수 있습니다. 그러나 다른 컨텍스트의 컴포넌트에서 다른 ID를 사용할 수 있는 요소를 만들 수도 있습니다. 이렇게 하면 외부 ID를 사용할 수 있다는 가정이 깨집니다. 따라서 엔진과 QML 툴링은 일반적으로 이러한 ID가 런타임에 어떤 유형으로 해석될지 미리 알 수 없습니다.

ComponentBehavior 프래그마를 사용하면 파일에 정의된 모든 내부 컴포넌트가 원래 컨텍스트 내에서만 객체를 생성하도록 제한할 수 있습니다. 컴포넌트가 컨텍스트에 바인딩되어 있으면 컴포넌트 내에서 동일한 파일에 있는 외부 컴포넌트의 ID를 안전하게 사용할 수 있습니다. 그러면 QML 툴링은 특정 유형의 외부 ID를 사용할 수 있다고 가정합니다.

컴포넌트를 컨텍스트에 바인딩하려면 Bound 인수를 지정하세요:

pragma ComponentBehavior: Bound

이는 이름이 충돌하는 경우 바인딩된 컴포넌트 외부에 정의된 ID가 컴포넌트에서 생성된 객체의 로컬 속성을 재정의한다는 것을 의미합니다. 그렇지 않으면 이후 버전의 모듈이 컴포넌트에 더 많은 프로퍼티를 추가할 수 있으므로 ID를 사용하는 것이 실제로 안전하지 않을 수 있습니다. 컴포넌트가 바인딩되지 않은 경우 로컬 프로퍼티는 컴포넌트 외부에 정의된 ID를 재정의하지만 컴포넌트 내부에 정의된 ID는 재정의하지 않습니다.

아래 예는 직사각형 색상의 r 속성이 아닌 id 색상을 사용하여 ListView 객체의 r 속성을 인쇄합니다.

pragma ComponentBehavior: Bound
import QtQuick

ListView {
 id: color
 property int r: 12
 model: 1

 delegate: Rectangle {
  Component.onCompleted: console.log(color.r)
 }
}

ComponentBehavior 의 기본값은 Unbound 입니다. 명시적으로 지정할 수도 있습니다. Qt XML의 향후 버전에서는 기본값이 Bound 로 변경됩니다.

컨텍스트에 바인딩된 델리게이트 컴포넌트는 인스턴스화 시 자체 프라이빗 컨텍스트를 수신하지 않습니다. 즉, 이 경우 모델 데이터는 필수 프로퍼티를 통해서만 전달할 수 있습니다. 컨텍스트 속성을 통해 모델 데이터를 전달하면 작동하지 않습니다. 이는 예를 들어 Instantiator, Repeater, ListView, TableView, GridView, TreeView 및 일반적으로 내부적으로 DelegateModel 을 사용하는 모든 델리게이트와 관련이 있습니다.

예를 들어 다음은 작동하지 않습니다:

pragma ComponentBehavior: Bound
import QtQuick

ListView {
 delegate: Rectangle {
     color: model.myColor
 }
}

ListViewdelegate 속성은 컴포넌트입니다. 따라서 여기서는 Rectangle 주위에 Component 가 암시적으로 생성됩니다. 해당 컴포넌트는 컨텍스트에 바인딩됩니다. ListView 에서 제공하는 컨텍스트 속성 model 을 수신하지 않습니다. 이를 작동시키려면 이런 식으로 작성해야 합니다:

pragma ComponentBehavior: Bound
import QtQuick

ListView {
 delegate: Rectangle {
     required property color myColor
     color: myColor
 }
}

QML 파일에 컴포넌트를 중첩할 수 있습니다. 이 프래그마는 아무리 깊게 중첩되어 있더라도 파일의 모든 컴포넌트에 적용됩니다.

함수 시그니처 동작

이 프라그마를 사용하면 함수에 대한 타입 어노테이션 처리 방식을 변경할 수 있습니다. Qt 6.7부터는 함수를 호출할 때 타입 어노테이션이 적용됩니다. 이전에는 QML 스크립트 컴파일러만 타입 어노테이션을 적용했습니다. 인터프리터와 JIT 컴파일러는 이를 무시했습니다. 이전에는 인수가 일치하지 않는 함수를 호출할 수 있었으므로 항상 유형 어노테이션을 적용하는 것은 이전 버전과 비교하여 동작이 변경된 것입니다.

Ignored 을 값으로 지정하면 QML 엔진과 QML 스크립트 컴파일러가 유형 어노테이션을 무시하므로 인터프리터와 JIT의 6.7 이전 동작이 복원됩니다. 결과적으로 미리 C++로 컴파일되는 코드가 줄어들고 더 많은 코드를 해석하거나 JIT 컴파일해야 합니다.

Enforced 을 값으로 지정하면 기본값이 명시적으로 지정됩니다: 유형 어노테이션이 항상 적용됩니다.

NativeMethodBehavior

검색된 객체와 다른 this 객체로 C++ 메서드를 호출하는 것은 역사적인 이유로 인해 깨졌습니다. 원본 객체는 this 객체로 사용됩니다. pragma NativeMethodBehavior: AcceptThisObject 을 설정하여 지정된 this 객체를 사용하도록 허용할 수 있습니다. RejectThisObject 을 지정하면 이전 동작이 유지됩니다.

이에 대한 예는 C++ 메서드와 'this' 객체에서 찾을 수 있습니다.

ValueTypeBehavior

이 프래그마를 사용하면 값 유형과 시퀀스가 처리되는 방식을 변경할 수 있습니다.

일반적으로 소문자 이름은 자바스크립트 코드에서 타입 이름이 될 수 없습니다. 이는 값 유형 이름이 소문자이기 때문에 발생하는 문제입니다. 이 프라그마의 값으로 Addressable 을 지정하여 이를 변경할 수 있습니다. Addressable 을 지정하면 자바스크립트 값을 특정 이름의 값 유형으로 명시적으로 강제 지정할 수 있습니다. 이 작업은 객체 유형에서와 마찬가지로 as 연산자를 사용하여 수행됩니다. 또한 instanceof 연산자를 사용하여 값 유형을 확인할 수도 있습니다:

pragma ValueTypeBehavior: Addressable
import QtQml

QtObject {
 property var a
 property real b: (a as rect).x
 property bool c: a instanceof rect

 property var rect // inaccessible. "rect" is a type name.
}

위 예제에서 rect 는 이제 유형 이름이므로 rect 이라는 프로퍼티를 섀도 처리합니다.

원하는 유형으로 명시적으로 형변환하면 툴링에 도움이 됩니다. 이를 통해 Qt Quick Compiler 가 다른 방법으로는 생성할 수 없는 효율적인 코드를 생성할 수 있습니다. 이러한 경우를 찾기 위해 qmllint를 사용할 수 있습니다.

기본 동작을 명시적으로 지정하는 데 사용할 수 있는 Inaddressable 값도 있습니다.

ValueTypeBehavior 프라그마의 또 다른 어트리뷰트는 Assertable 으로, Qt 6.8에 도입되었습니다. Qt 6.6과 6.7의 실수로 인해 위의 a as rectarect 인지를 검사할 뿐만 아니라 a 이 호환되는 유형인 경우 rect 을 생성합니다. 이는 명백히 타입 어설션이 해야 할 일이 아닙니다. Assertable 을 지정하면 이러한 동작을 방지하고 값 유형에 대한 유형 어설션이 해당 유형만 확인하도록 제한합니다. as 와 함께 값 유형을 사용하려는 경우 항상 지정해야 합니다. 어쨌든 값 유형에 대한 유형 어설션이 실패하면 결과는 undefined 입니다.

instanceof 는 가능한 모든 유형 강제성이 아닌 상속만 검사하므로 이 문제가 발생하지 않습니다.

참고: intdouble 유형과 함께 as 을 사용하는 것은 자바스크립트 규칙에 따라 계산 결과가 정수와 동일한 값을 갖더라도 부동 소수점 숫자가 되므로 바람직하지 않습니다. 반대로 자바스크립트에서 선언한 정수 상수는 QML의 타입 매핑 규칙에 따라 더블이 아닙니다. 또한 intdouble 은 예약어입니다. 이러한 유형은 유형 네임스페이스를 통해서만 주소를 지정할 수 있습니다.

값 유형과 시퀀스는 일반적으로 참조로 취급됩니다. 즉, 속성에서 값 유형 인스턴스를 로컬 값으로 검색한 다음 로컬 값을 변경하면 원래 속성도 변경됩니다. 또한 원래 프로퍼티를 명시적으로 작성하면 로컬 값도 업데이트됩니다. 이 동작은 많은 곳에서 다소 직관적이지 않으므로 이 동작에 의존해서는 안 됩니다. ValueTypeBehavior 프래그마의 CopyReference 값은 이 동작을 변경하기 위한 실험적인 옵션입니다. 이 값을 사용해서는 안 됩니다. Copy 을 지정하면 모든 값 유형이 실제 복사본으로 취급됩니다. Reference 을 지정하면 기본 동작이 명시적으로 지정됩니다.

Copy 대신 값 유형 및 시퀀스에 대한 참조가 부작용의 영향을 받을 수 있는 경우 언제든지 명시적으로 다시 로드해야 합니다. 부작용은 함수를 호출하거나 속성을 필수적으로 설정할 때마다 발생할 수 있습니다. qmllint는 이에 대한 지침을 제공합니다. 예를 들어, 다음 코드에서 f 변수는 width 을 작성한 후 부작용의 영향을 받습니다. 이는 파생된 유형이나 Binding 요소에 width 가 변경될 때 font 을 업데이트하는 바인딩이 있을 수 있기 때문입니다.

import QtQuick
Text {
 function a() : real {
     var f = font;
     width = f.pixelSize;
     return f.pointSize;
 }
}

이 문제를 해결하기 위해 width 에 대한 쓰기 작업에서 f 을 유지하지 않을 수 있습니다:

import QtQuick
Text {
 function a() : real {
     var f = font;
     width = f.pixelSize;
     f = font;
     return f.pointSize;
 }
}

로 단축할 수 있습니다:

import QtQuick
Text {
 function a() : real {
     width = font.pixelSize;
     return font.pointSize;
 }
}

font 속성을 다시 검색하는 데 비용이 많이 든다고 생각할 수 있지만, 실제로는 QML 엔진이 값 유형 참조를 읽을 때마다 자동으로 새로 고칩니다. 따라서 첫 번째 버전보다 비용이 더 많이 들지는 않지만 동일한 연산을 더 명확하게 표현할 수 있습니다.

번역기

이 프래그마를 사용하면 파일에서 번역에 대한 컨텍스트를 설정할 수 있습니다.

pragma Translator: myTranslationContext
pragma Translator: "myTranslationContext"

QML을 사용한 국제화에 대한 자세한 내용은 qsTr 사용을 참조하세요.

가져오기

문서에서 엔진이 문서 내에서 참조된 QML 객체 유형을 로드할 수 있도록 하려면 문서에서 필요한 모듈 또는 유형 네임스페이스를 임포트해야 합니다. 기본적으로 문서는 동일한 디렉터리에 있는 .qml 파일을 통해 정의된 모든 QML 객체 유형에 액세스할 수 있으며, 문서에서 다른 객체 유형을 참조해야 하는 경우 해당 유형이 등록되어 있는 유형 네임스페이스를 임포트해야 합니다.

QML에는 C 또는 C++와 달리 QML engine 에 표시하기 전에 문서를 수정하는 전처리기가 없습니다. import 문은 문서의 코드를 복사하여 앞에 추가하는 것이 아니라 문서에서 발견된 유형 참조를 해결하는 방법을 QML 엔진에 지시합니다. JavaScript 블록이나 속성 바인딩 내에서 만들어진 타입 참조를 포함하여 QML 문서에 존재하는 모든 타입 참조(예: RectangleListView )는 오직 import 문을 기반으로만 확인됩니다. import QtQuick 2.0 과 같은 import 문이 하나 이상 있어야 합니다.

QML 가져오기에 대한 자세한 내용은 QML 구문 - 가져오기 문 문서를 참조하세요.

루트 객체 선언

QML 문서는 인스턴스화할 수 있는 객체의 계층구조를 설명합니다. 각 객체 정의에는 유형, ID 및 객체 이름, 속성, 메서드, 시그널 및 시그널 핸들러와 같은 특정 구조가 있습니다.

QML 파일에는 하나의 루트 객체 정의만 포함되어야 합니다. 다음은 유효하지 않으며 오류가 발생합니다:

// MyQmlFile.qml
import QtQuick 2.0

Rectangle { width: 200; height: 200; color: "red" }
Rectangle { width: 200; height: 200; color: "blue" }    // invalid!

.qml 파일은 단일 QML 객체 정의를 캡슐화하는 QML 유형을 자동으로 정의하기 때문입니다. 이에 대해서는 문서에서 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.