이 페이지에서

QML 객체 속성

모든 QML 객체 유형에는 정의된 속성 집합이 있습니다. 객체 유형의 각 인스턴스는 해당 객체 유형에 대해 정의된 속성 집합을 가지고 생성됩니다. 지정할 수 있는 속성에는 여러 가지 종류가 있으며, 이에 대해서는 아래에서 설명합니다.

객체 선언 내의 속성

QML 문서의 객체 선언은 새로운 유형을 정의합니다. 또한, 새로 정의된 유형의 인스턴스가 생성될 경우 인스턴스화될 객체 계층 구조를 선언합니다.

QML 객체 유형의 속성 유형은 다음과 같습니다:

  • id 속성
  • 속성(property) 속성
  • 신호(signal) 속성
  • 신호 핸들러 속성
  • 메서드 속성
  • 부착된 속성 및 부착된 신호 핸들러 속성
  • 열거형 속성

이러한 속성에 대해서는 아래에서 자세히 설명합니다.

id 속성

QML 요소는 최대 하나의 id 속성만 가질 수 있습니다. 이 속성은 언어 자체에서 제공되며, 어떤 QML 객체 유형으로도 재정의하거나 오버라이드할 수 없습니다.

객체 인스턴스의 id 속성에 값을 할당하여 다른 객체가 해당 객체를 식별하고 참조할 수 있도록 할 수 있습니다. 이 식별자( id )는 소문자나 밑줄(_)로 시작해야 하며, 문자, 숫자 및 밑줄 이외의 문자를 포함할 수 없습니다. 또한 JavaScript 키워드일 수도 없습니다. 이러한 키워드 목록은 ECMAScript 언어 사양서를 참조하십시오.

QML에서 ‘as’와 같이 JavaScript 식별자로 적합하지 않은 이름을 사용하면, JavaScript에서 해당 객체를 참조할 수 없게 되어 id가 사실상 무용지물이 됩니다. 다만 C++에서 QQmlContext 를 사용하여 이러한 id와상호작용하는 것은 여전히 가능합니다.

다음은 ` TextInput ` 객체와 ` Text ` 객체의 예시입니다. ` TextInput ` 객체의 ` id ` 값은 "myTextInput"으로 설정되어 있습니다. ` Text ` 객체는 ` myTextInput.text`을 참조하여 ` text ` 속성의 값을 ` TextInput`의 ` text ` 속성과 동일하게 설정합니다. 이제 두 항목 모두 동일한 텍스트를 표시합니다:

import QtQuick

Column {
    width: 200; height: 200

    TextInput { id: myTextInput; text: "Hello World" }

    Text { text: myTextInput.text }
}

객체는 생성된 QML 컨텍스트 내의 어느 곳에서나 id 를 통해 참조할 수 있습니다. 따라서 id 값은 해당 컨텍스트 내에서 항상 고유해야 합니다. 자세한 내용은 ‘범위 및 이름 해결(Scope and Naming Resolution )’을 참조하십시오.

컨텍스트는 QQmlContext 계층 구조를 통해 C++에도 노출됩니다. 예를 들어, qmlContext 함수를 통해 특정 객체의 컨텍스트를 가져온 다음, 동일한 컨텍스트에 속한 다른 객체들을 조회할 수 있습니다:

QObject *textInput = qmlContext(theColumn)->objectForName("myTextInput");

객체 인스턴스가 생성되면 id 속성의 값은 변경할 수 없습니다. 겉보기에는 일반적인 속성처럼 보일 수 있지만, id 속성은 일반적인 property 속성이 아니며, 이에 특별한 의미론이 적용됩니다. 예를 들어, 위의 예제에서 myTextInput.id 에 접근하는 것은 불가능합니다.

속성

속성은 객체의 속성으로, 정적 값을 할당하거나 동적 표현식에 바인딩할 수 있습니다. 속성의 값은 다른 객체에서 읽을 수 있습니다. 일반적으로 특정 QML 유형이 특정 속성에 대해 이를 명시적으로 금지하지 않는 한, 다른 객체에서도 이 값을 수정할 수 있습니다.

속성 정의

C++에서 유형에 대한 속성을 정의하려면 클래스의 ` Q_PROPERTY `를 등록한 다음, 이를 QML 유형 시스템에 등록하면 됩니다. 또는 QML 문서의 객체 선언에서 다음 구문을 사용하여 객체 유형의 사용자 정의 속성을 정의할 수도 있습니다:

[default] [virtual] [override] [final] [required] [readonly] property <propertyType> <propertyName>

이러한 방식으로 객체 선언을 통해 특정 값을 외부 객체에 노출하거나 내부 상태를 보다 쉽게 관리할 수 있습니다.

속성 이름은 소문자로 시작해야 하며, 영문자, 숫자 및 밑줄(_)만 포함할 수 있습니다. 자바스크립트 예약어는 유효한 속성 이름이 아닙니다. default, required, readonly, virtual, override, final 키워드는 선택 사항이며, 선언되는 속성의 의미를 수정합니다. 각 키워드의 구체적인 의미에 대한 자세한 내용은 이후 섹션에서 다룰 기본 속성, 필수 속성, 읽기 전용 속성 및 재정의 의미에 관한 내용을 참조하십시오.

사용자 정의 속성을 선언하면 해당 속성에 대한 값 변경 신호가 암시적으로 생성되며, on<PropertyName>Changed라는 관련 신호 핸들러도 생성됩니다. 여기서 <PropertyName> 은 속성의 이름이며, 첫 글자는 대문자로 표기됩니다.

예를 들어, 다음 객체 선언은 Rectangle 기본 유형에서 파생된 새로운 유형을 정의합니다. 이 유형에는 두 개의 새로운 속성이 있으며, 그중 하나의 속성에 대해 신호 핸들러가 구현되어 있습니다.

Rectangle {
    property color previousColor
    property color nextColor
    onNextColorChanged: console.log("The next color will be: " + nextColor.toString())
}
사용자 정의 속성 정의에서 허용되는 유형

모든 QML 값 유형 을 사용자 정의 속성 유형으로 사용할 수 있습니다. 예를 들어, 다음은 모두 유효한 속성 선언입니다:

Item {
    property int someNumber
    property string someString
    property url someUrl
}

(열거형 값은 단순히 정수 값이므로, 대신 int 유형으로 참조할 수 있습니다.)

일부 값 유형은 ` QtQuick ` 모듈에서 제공되므로, 해당 모듈을 임포트하지 않으면 속성 유형으로 사용할 수 없습니다. 자세한 내용은 QML 값 유형 문서를 참조하십시오.

var 값 유형은 목록과 객체를 포함하여 모든 유형의 값을 담을 수 있는 일반적인 자리 표시자 유형이라는 점에 유의하십시오:

property var someNumber: 1.5
property var someString: "abc"
property var someBool: true
property var someList: [1, 2, "three", "four"]
property var someObject: Rectangle { width: 100; height: 100; color: "red" }

또한, 모든 QML 객체 유형을 속성 유형으로 사용할 수 있습니다. 예를 들어:

property Item someItem
property Rectangle someRectangle

이는 사용자 정의 QML 유형에도 적용됩니다. ColorfulButton.qml 이라는 이름의 파일(클라이언트가 임포트한 디렉터리 내)에 QML 유형이 정의된 경우, ColorfulButton 유형의 속성도 유효합니다.

속성 값 할당

객체 인스턴스의 속성 값은 다음 두 가지 방법으로 지정할 수 있습니다:

  • 초기화 시의 값 할당
  • 명령형 값 할당

두 경우 모두 값은 정적 값이거나 바인딩 표현식의 결과값일 수 있습니다.

초기화 시 값 할당

초기화 시 속성에 값을 할당하는 구문은 다음과 같습니다:

<propertyName> : <value>

원하는 경우, 초기화 값 할당을 객체 선언 내의 속성 정의와 결합할 수 있습니다. 이 경우 속성 정의의 구문은 다음과 같습니다:

[default] property <propertyType> <propertyName> : <value>

다음은 속성 값 초기화의 예입니다:

import QtQuick

Rectangle {
    color: "red"
    property color nextColor: "blue" // combined property declaration and initialization
}
명령형 값 할당

명령형 값 할당은 명령형 JavaScript 코드에서 속성 값(정적 값 또는 바인딩 표현식)을 속성에 할당하는 것을 말합니다. 명령형 값 할당의 구문은 아래와 같이 JavaScript 할당 연산자 그대로입니다:

[<objectId>.]<propertyName> = value

명령형 값 할당의 예는 다음과 같습니다:

import QtQuick

Rectangle {
    id: rect
    Component.onCompleted: {
        rect.color = "red"
    }
}

정적 값과 바인딩 표현식 값

앞서 언급했듯이, 속성에 할당될 수 있는 값에는 정적 값과 바인딩 표현식 값, 두 가지 종류가 있습니다. 후자는 속성 바인딩이라고도 합니다.

종류의미
정적 값다른 속성에 의존하지 않는 상수 값.
바인딩 표현식속성과 다른 속성 간의 관계를 설명하는 JavaScript 표현식입니다. 이 표현식 내의 변수들은 해당 속성의 종속성이라고 합니다.

QML 엔진은 속성과 그 종속성 간의 관계를 강제 적용합니다. 종속성 중 하나라도 값이 변경되면, QML 엔진은 바인딩 표현식을 자동으로 재평가하고 새로운 결과를 해당 속성에 할당합니다.

다음은 두 가지 유형의 값이 속성에 할당되는 예를 보여줍니다:

import QtQuick

Rectangle {
    // both of these are static value assignments on initialization
    width: 400
    height: 200

    Rectangle {
        // both of these are binding expression value assignments on initialization
        width: parent.width / 2
        height: parent.height
    }
}

참고: 바인딩 표현식을 명령형방식으로 할당하려면 , 해당 표현식을 ` Qt.binding()`에 전달되는 함수 내에 포함시킨 다음, `Qt.binding()`이 반환하는 값을 속성에 할당해야 합니다. 반면, 초기화 시 바인딩 표현식을 할당할 때는 `Qt.binding()`을 사용해서는 안 됩니다. 자세한 내용은 속성 바인딩을 참조하십시오.

타입 안전성

속성은 유형 안전합니다. 속성에는 해당 속성 유형과 일치하는 값만 할당할 수 있습니다.

예를 들어, 속성이 int형인데 문자열을 할당하려고 하면 오류가 발생합니다:

property int volume: "four"  // generates an error; the property's object will not be loaded

마찬가지로 실행 중에 속성에 잘못된 유형의 값을 할당하려고 하면 새로운 값이 할당되지 않고 오류가 발생합니다.

일부 속성 유형은 자연스러운 값 표현 형식이 없으며, 이러한 속성 유형의 경우 QML 엔진이 자동으로 문자열을 유형화된 값으로 변환합니다. 따라서 예를 들어, ` color ` 유형의 속성은 문자열이 아닌 색상을 저장하지만, 오류 없이 ` "red" `과 같은 문자열을 색상 속성에 할당할 수 있습니다.

기본적으로 지원되는 속성 유형 목록은 QML 값 유형을 참조하십시오. 또한, 사용 가능한 모든 QML 객체 유형도 속성 유형으로 사용할 수 있습니다.

특수 속성 유형

객체 목록 속성 속성

list 유형의 속성에는 QML 객체 유형 값의 목록을 할당할 수 있습니다. 객체 목록 값을 정의하는 구문은 대괄호로 묶인 쉼표로 구분된 목록입니다:

[ <item 1>, <item 2>, ... ]

예를 들어, ` Item ` 유형에는 ` State ` 유형 객체의 목록을 담는 ` states ` 속성이 있습니다. 아래 코드는 이 속성의 값을 세 개의 ` State ` 객체로 구성된 목록으로 초기화합니다:

import QtQuick

Item {
    states: [
        State { name: "loading" },
        State { name: "running" },
        State { name: "stopped" }
    ]
}

목록에 항목이 하나만 포함된 경우, 대괄호를 생략할 수 있습니다:

import QtQuick

Item {
    states: State { name: "running" }
}

list 형 속성은 객체 선언에서 다음 구문을 사용하여 지정할 수 있습니다:

[default] property list<<ObjectType>> propertyName

또한 다른 속성 선언과 마찬가지로, 다음 구문을 사용하여 속성 초기화를 속성 선언과 결합할 수 있습니다:

[default] property list<<ObjectType>> propertyName: <value>

다음은 리스트 속성 선언의 예시입니다:

import QtQuick

Rectangle {
    // declaration without initialization
    property list<Rectangle> siblingRects

    // declaration with initialization
    property list<Rectangle> childRects: [
        Rectangle { color: "red" },
        Rectangle { color: "blue"}
    ]
}

반드시 QML 객체 유형 값일 필요는 없는 값들의 목록을 저장할 속성을 선언하려는 경우, 대신 ` var ` 속성을 선언해야 합니다.

그룹화된 속성

경우에 따라 속성에는 하위 속성 속성들이 논리적으로 그룹화되어 포함될 수 있습니다. 이러한 하위 속성 속성에는 점 표기법(dot notation)이나 그룹 표기법(group notation)을 사용하여 값을 할당할 수 있습니다.

예를 들어, ` Text ` 유형에는 ` font ` 속성이 있습니다. 아래 예시에서 첫 번째 ` Text ` 객체는 점 표기법을 사용하여 ` font ` 값을 초기화하는 반면, 두 번째 객체는 그룹 표기법을 사용합니다:

Text {
    //dot notation
    font.pixelSize: 12
    font.bold: true
}

Text {
    //group notation
    font { pixelSize: 12; bold: true }
}

그룹화된 속성 구문은 유형 자체에 하위 속성이 있는 모든 속성에 사용할 수 있습니다. 이는 별도의 속성 유형이 아닌 표기법일 뿐입니다. 즉, 속성이 ` font `과 같은 값 유형을 가지는지, 아니면 객체 유형을 가지는지는 구문에 아무런 영향을 미치지 않습니다.

다만, 속성의 유형은 엔진이 수행해야 할 작업에 영향을 미칩니다:

  • 속성이 값 유형을 포함하는 경우, 엔진은 해당 값을 읽은 후 수정하고 다시 기록합니다. 따라서 해당 속성은 쓰기 가능해야 합니다.
  • 속성이 객체 유형을 포함하는 경우, 할당 연산은 속성이 현재 보유하고 있는 객체에 기록됩니다. 할당 연산이 적용될 때 해당 객체는 null이어서는 안 됩니다. 속성 자체는 읽기 전용이거나 쓰기 가능할 수 있습니다. 속성을 읽기 전용으로 설정하는 것은 QML 코드가 하위 속성이 속한 객체를 대체하는 것을 방지하여, 그룹화된 속성이 어떤 객체에 적용되는지에 대한 혼란을 피하는 방법입니다. 일반적으로 이는 좋은 방법입니다.

하위 속성 이름은 실행 시점에 속성이 보유한 객체의 유형이 아닌, 속성이 선언된 유형을 기준으로 해결됩니다. 또한 동일한 객체 정의 내에서 동일한 속성에 대해 두 가지 형식을 모두 사용할 수 없습니다. 즉, 속성에 객체를 할당하거나 하위 속성에 할당하는 방법 중 하나만 선택해야 합니다.

속성 별칭

속성 별칭은 다른 속성에 대한 참조를 보유하는 속성입니다. 속성을 위해 새롭고 고유한 저장 공간을 할당하는 일반적인 속성 정의와 달리, 속성 별칭은 새로 선언된 속성(별칭 속성이라고 함)을 기존 속성(별칭 대상 속성)에 대한 직접 참조로 연결합니다.

속성 별칭 선언은 일반 속성 정의와 비슷하지만, 속성 유형 대신 ` alias ` 키워드가 필요하며, 속성 선언의 우측항은 유효한 별칭 참조여야 한다는 점이 다릅니다:

[default] property alias <name>: <alias reference>

일반 속성과 달리, 별칭에는 다음과 같은 제한 사항이 있습니다:

  • 앨리어스는 해당 앨리어스가 선언된 타입의 범위 내에 있는 객체나 객체의 속성만을 참조할 수 있습니다.
  • 임의의 자바스크립트 표현식을 포함할 수 없습니다.
  • 해당 유형의 범위 밖에서 선언된 객체를 참조할 수 없습니다.
  • 일반 속성의 선택적 기본값과 달리, 별칭 참조는 선택 사항이 아니며, 별칭을 처음 선언할 때 반드시 별칭 참조를 제공해야 합니다.
  • 부착된 속성을 참조할 수 없습니다.
  • 깊이가 3 이상인 계층 구조 내부의 속성을 참조할 수 없습니다. 다음 코드는 작동하지 않습니다:
    property alias color: myItem.myRect.border.color
    
    Item {
        id: myItem
        property Rectangle myRect
    }

    그러나 깊이가 2 수준 이하인 속성에 대한 별칭은 정상적으로 작동합니다.

    property alias color: rectangle.border.color
    
    Rectangle {
        id: rectangle
    }

예를 들어, 아래는 Button 타입으로, buttonText 이라는 별칭 속성을 가지고 있으며, 이 속성은 Text 자식 객체의 text 객체에 연결되어 있습니다:

// Button.qml
import QtQuick

Rectangle {
    property alias buttonText: textItem.text

    width: 100; height: 30; color: "yellow"

    Text { id: textItem }
}

다음 코드는 자식 객체인 Text 에 대해 정의된 텍스트 문자열을 가진 Button 을 생성합니다:

Button { buttonText: "Click Me" }

여기서 buttonText 을 수정하면 textItem.text 값이 직접 수정되며, 다른 값을 변경한 후 textItem.text를 업데이트하는 방식이 아닙니다. 만약 buttonText 가 별칭이 아니었다면, 속성 바인딩은 양방향으로 작동하지 않기 때문에 해당 값을 변경해도 실제로 표시되는 텍스트는 전혀 변경되지 않았을 것입니다. 즉, textItem.text가 변경되면 buttonText 값도 변경되었겠지만, 그 반대의 경우는 아니었을 것입니다.

속성 별칭과 유형

속성 별칭에는 명시적인 형식 지정을 할 수 없습니다. 속성 별칭의 형식은 해당 별칭이 참조하는 속성이나 객체의 선언된 형식입니다. 따라서 id를 통해 참조되는 객체에 대해 인라인으로 추가 속성이 선언된 별칭을 생성하는 경우, 해당 추가 속성들은 별칭을 통해 접근할 수 없습니다:

// MyItem.qml
Item {
    property alias inner: innerItem

    Item {
        id: innerItem
        property int extraProperty
    }
}

inner는 단순히 Item 일 뿐이므로, 이 컴포넌트 외부에서는 inner.extraProperty 를 초기화할 수 없습니다:

// main.qml
MyItem {
    inner.extraProperty: 5 // fails
}

하지만 inner 객체를 별도의 .qml 파일을 가진 독립된 컴포넌트로 추출하면, 대신 해당 컴포넌트를 인스턴스화하여 별칭을 통해 모든 속성을 사용할 수 있습니다:

// MainItem.qml
Item {
    // Now you can access inner.extraProperty, as inner is now an ExtraItem
    property alias inner: innerItem

    ExtraItem {
        id: innerItem
    }
}

// ExtraItem.qml
Item {
    property int extraProperty
}

기본 속성

객체 정의에는 하나의 기본 속성만 가질 수 있습니다. 속성을 명시하지 않고 한 객체가 다른 객체 내에 직접 중첩될 경우, 해당 객체는 자동으로 외곽 객체의 기본 속성에 할당됩니다.

선택적 키워드 ` default `를 사용하여 속성을 선언하면 해당 속성이 기본 속성으로 지정됩니다. 예를 들어, 기본 속성이 ` focusItem`인 `Framer.qml` 파일이 있다고 가정해 봅시다:

// Framer.qml
import QtQuick

Row {
    default property Item focusItem
    property Item leftItem: Rectangle {
        width: 10
        height: parent.height
        color: "red"
    }
    property Item rightItem: Rectangle {
        width: 10
        height: parent.height
        color: "blue"
    }
    children: [leftItem, focusItem, rightItem]
}

' focusItem ' 값은 다음과 같이 ' Framer ' 객체 정의에서 할당될 수 있습니다:

Framer {
    Text { text: "Hello, world!" }
}

이는 다음 코드와 정확히 동일한 효과를 냅니다:

Framer {
    focusItem: Text { text: "Hello, world!" }
}

그러나 focusItem 속성이 기본 속성으로 지정되었으므로, 이 속성에 Text 객체를 명시적으로 할당할 필요는 없습니다.

어떤 유형의 속성이든 default 속성으로 지정할 수 있지만, 일반적으로는 var, 객체 유형 및 해당 시퀀스 유형의 속성만 지정하는 것이 유용합니다: 기본 속성에는 객체 인스턴스만 할당되므로, 예를 들어 default 문자열 속성을 지정하는 것은 QML에서 아무런 이점이 없습니다.

다음 TextHolder 타입을 고려해 보겠습니다:

// TextHolder.qml
Item {
    property default string mytext
}

그 자체로는 문제가 없습니다. 하지만 속성 이름을 명시적으로 언급하지 않으면 mytext 에 문자열 리터럴을 할당할 수 없습니다:

TextHolder {
  /* The following would be a syntax error, and will not assign
     to the mytext property:
  "some text"

  The line below is the only way to assign the value:
  \1/
  mytext: "some text"
}

Item 을 기반으로 한 모든 유형에는 children 속성에 명시적으로 추가하지 않아도 자식 객체를 추가할 수 있다는 점을 알 수 있습니다. 이는 Item 의 기본 속성이 data 속성이며, Item 에 대해 이 목록에 추가된 모든 항목이 자동으로 children 목록에 추가되기 때문입니다.

기본 속성은 항목의 자식 노드를 재할당하는 데 유용할 수 있습니다. 예를 들어:

Item {
    default property alias content: inner.children

    Item {
        id: inner
    }
}

기본 속성 별칭을 inner.children 로 설정하면, 외부 항목의 자식으로 할당된 모든 객체가 자동으로 내부 항목의 자식으로 재할당됩니다.

경고: 요소의 기본 목록 속성 값설정은 암시적 또는 명시적으로 수행할 수 있습니다. 단일 요소 정의 내에서 이 두 가지 방법을 혼합해서는 안 되며, 그렇지 않을 경우 목록 내 요소의 순서가 정의되지 않게 됩니다.

Item {
    // Use either implicit or explicit assignement to the default list property but not both!
    Rectangle { width: 40 }            // implicit
    data: [ Rectangle { width: 100 } ] // explicit
}

오버라이드 의미론

기본적으로 속성은 섀도잉될 수 있습니다. 즉, 파생된 QML 유형에서 속성을 재선언할 수 있으며, 이때 새로운 유형과 새로운 속성을 사용할 수도 있습니다. 이로 인해 동일한 이름의 두 속성이 생성되지만, 주어진 컨텍스트에서는 그중 하나에만 접근할 수 있습니다. 이는 원하는 결과가 되는 경우가 거의 없습니다. 대개 이는 의도치 않게 발생하며, 대부분의 경우 그 결과는 상당히 혼란스럽습니다. 또한, 가림 현상은 도구 사용에 부정적인 영향을 미칩니다.

이를 해결하기 위해 ` virtual`, ` override`, ` final ` 키워드와 추가적인 경고 및 오류 메시지가 도입되었습니다.

경고 및 오류를 포함한 자세한 내용과 포괄적인 예제는 ‘속성 가림 및 재정의 의미론(Property Shadowing and Override Semantics )’ 페이지를 참조하십시오.

필수 속성

객체 선언에서는 ` required ` 키워드를 사용하여 속성을 필수로 정의할 수 있습니다. 구문은 다음과 같습니다.

required property <propertyType> <propertyName>

이름에서 알 수 있듯이, 필수 속성은 객체의 인스턴스가 생성될 때 반드시 설정되어야 합니다. 이 규칙을 위반하면 정적으로 감지될 경우 QML 애플리케이션이 시작되지 않습니다. 동적으로 인스턴스화되는 QML 컴포넌트(예: Qt.createComponent()를 통해)의 경우, 이 규칙을 위반하면 경고가 발생하고 반환 값이 null이 됩니다.

다음과 같이 기존 속성을 필수 속성으로 지정할 수 있습니다.

required <propertyName>

다음 예제는 color 속성을 항상 지정해야 하는 사용자 정의 Rectangle 컴포넌트를 만드는 방법을 보여줍니다.

// ColorRectangle.qml
Rectangle {
    required color
}

참고: QML에서는 필수 속성에 초기값을 할당할수 없습니다 . 이는 필수 속성의 의도된 사용 방식에 정면으로 위배되기 때문입니다.

필수 속성은 모델-뷰-델리게이트 코드에서 특별한 역할을 합니다. 뷰의 델리게이트에 뷰 모델의 역할 이름과 일치하는 이름의 필수 속성이 있는 경우, 해당 속성은 모델의 해당 값으로 초기화됩니다. 자세한 내용은 Qt Quick 페이지의 ‘모델 및 뷰’를 참조하십시오.

C++에서 필수 속성을 초기화하는 방법은 QQmlComponent::createWithInitialProperties, QQmlApplicationEngine::setInitialProperties 및 QQuickView::setInitialProperties 을 참조하십시오.

읽기 전용 속성

객체 선언에서는 다음 구문을 사용하여 ` readonly ` 키워드로 읽기 전용 속성을 정의할 수 있습니다.

readonly property <propertyType> <propertyName> : <value>

읽기 전용 속성은 초기화 시 정적 값이나 바인딩 표현식을 할당해야 합니다. 읽기 전용 속성이 초기화된 후에는 해당 정적 값이나 바인딩 표현식을 더 이상 변경할 수 없습니다.

예를 들어, 아래 Component.onCompleted 블록의 코드는 유효하지 않습니다.

Item {
    readonly property int someNumber: 10

    Component.onCompleted: someNumber = 20  // TypeError: Cannot assign to read-only property
}

참고: 읽기 전용속성은 기본 속성이 될 수 없습니다.

속성 수정자 객체

속성에는 속성 값 수정자 객체가 연관될 수 있습니다. 특정 속성과 연관된 속성 수정자 유형의 인스턴스를 선언하는 구문은 다음과 같습니다:

<PropertyModifierTypeName> on <propertyName> {
    // attributes of the object instance
}

이를 일반적으로 "on" 구문이라고 합니다.

위의 구문은 사실 기존 속성에 작용하는 객체를 인스턴스화하는 객체 선언이라는 점에 유의해야 합니다.

특정 속성 수정자 유형은 특정 속성 유형에만 적용될 수 있지만, 이는 언어에 의해 강제되는 것은 아닙니다. 예를 들어, QtQuick 에서 제공하는 ` NumberAnimation ` 유형은 숫자형(예: ` int ` 또는 ` real`) 속성에 대해서만 애니메이션을 적용합니다. 숫자형이 아닌 속성에 ` NumberAnimation `를 사용하려고 해도 오류는 발생하지 않지만, 해당 속성에는 애니메이션이 적용되지 않습니다. 특정 속성 유형과 연관되었을 때 속성 수정자 유형의 동작은 해당 구현에 의해 정의됩니다.

신호 속성

신호는 어떤 이벤트가 발생했음을 객체가 알리는 알림입니다. 예를 들어, 속성이 변경되었거나, 애니메이션이 시작되거나 중지되었거나, 이미지가 다운로드된 경우 등이 있습니다. 예를 들어, MouseArea 유형에는 사용자가 마우스 영역 내부를 클릭할 때 발송되는 clicked 신호가 있습니다.

특정 신호가 발송될 때마다 객체는 신호 핸들러를 통해 알림을 받을 수 있습니다. 신호 핸들러는 on<Signal> 구문으로 선언되며, 여기서 <Signal> 은 신호의 이름으로, 첫 글자는 대문자로 표기합니다. 신호 핸들러는 신호를 방출하는 객체의 정의 내에서 선언되어야 하며, 핸들러에는 신호 핸들러가 호출될 때 실행될 자바스크립트 코드 블록이 포함되어야 합니다.

예를 들어, 아래의 onClicked 신호 핸들러는 ` MouseArea ` 객체 정의 내에서 선언되며, ` MouseArea `을 클릭하면 호출되어 콘솔 메시지가 출력됩니다:

import QtQuick

Item {
    width: 100; height: 100

    MouseArea {
        anchors.fill: parent
        onClicked: {
            console.log("Click!")
        }
    }
}

신호 속성 정의

C++에서 유형에 대한 신호를 정의하려면 클래스의 ` Q_SIGNAL `를 등록한 다음, 이를 QML 유형 시스템에 등록하면 됩니다. 또는 QML 문서의 객체 선언에서 다음 구문을 사용하여 객체 유형에 대한 사용자 정의 신호를 정의할 수도 있습니다:

signal <signalName>[([<parameterName>: <parameterType>[, ...]])]

동일한 타입 블록 내에서 동일한 이름을 가진 두 개의 신호나 메서드를 선언하려고 하면 오류가 발생합니다. 그러나 새로운 신호는 해당 타입에 이미 존재하는 신호의 이름을 재사용할 수 있습니다. (기존 신호가 숨겨져 접근할 수 없게 될 수 있으므로, 이 작업은 신중하게 수행해야 합니다.)

다음은 신호 선언의 세 가지 예시입니다:

import QtQuick

Item {
    signal clicked
    signal hovered()
    signal actionPerformed(action: string, actionResult: int)
}

속성 스타일 구문을 사용하여 신호 매개변수를 지정할 수도 있습니다:

signal actionCanceled(string action)

메서드 선언과의 일관성을 유지하기 위해 콜론을 사용하는 타입 선언 방식을 선호해야 합니다.

신호에 매개변수가 없는 경우, "()" 괄호는 생략 가능합니다. 매개변수를 사용하는 경우, 위의 actionPerformed 신호에 대한 string 및 int 인자와 마찬가지로 매개변수 유형을 선언해야 합니다. 허용되는 매개변수 유형은 이 페이지의 ‘속성 속성 정의(Defining Property Attributes )’ 항목에 나열된 것과 동일합니다.

신호를 발신하려면 메서드로 호출하십시오. 신호가 발신되면 관련 신호 핸들러가 호출되며, 핸들러는 정의된 신호 인자 이름을 사용하여 각 인자에 접근할 수 있습니다.

속성 변경 신호

QML 유형은 또한 앞서 속성 속성 섹션에서 설명한 바와 같이, 속성 값이 변경될 때마다 발송되는 내장 속성 변경 신호를 제공합니다. 이러한 신호가 왜 유용한지, 그리고 어떻게 사용하는지에 대한 자세한 내용은 뒤따르는 속성 변경 신호 핸들러 섹션을 참조하십시오.

신호 핸들러 속성

신호 핸들러는 특수한 종류의 메서드 속성으로, 관련 신호가 발생될 때마다 QML 엔진에 의해 메서드 구현이 호출됩니다. QML에서 객체 정의에 신호를 추가하면 해당 객체 정의에 관련 신호 핸들러가 자동으로 추가되며, 기본적으로 이 핸들러의 구현은 비어 있습니다. 클라이언트는 프로그램 로직을 구현하기 위해 구현체를 제공할 수 있습니다.

다음의 ` SquareButton ` 타입을 예로 들어 보겠습니다. 이 타입의 정의는 아래와 같이 ` SquareButton.qml ` 파일에 제공되며, ` activated ` 및 ` deactivated` 신호가 포함되어 있습니다:

// SquareButton.qml
Rectangle {
    id: root

    signal activated(xPosition: real, yPosition: real)
    signal deactivated

    property int side: 100
    width: side; height: side

    MouseArea {
        anchors.fill: parent
        onReleased: root.deactivated()
        onPressed: mouse => root.activated(mouse.x, mouse.y)
    }
}

이러한 신호는 동일한 디렉터리에 있는 다른 QML 파일 내의 모든 ` SquareButton ` 객체가 수신할 수 있으며, 해당 파일에서 클라이언트가 신호 핸들러의 구현을 제공합니다:

// myapplication.qml
SquareButton {
    onDeactivated: console.log("Deactivated!")
    onActivated: (xPosition, yPosition) => {
        console.log(`Activated at ${xPosition}, ${yPosition}`)
    }
}

신호가 이미 매개변수 유형을 명시하고 있으므로, 신호 핸들러는 매개변수 유형을 별도로 선언할 필요가 없습니다. 위에 표시된 화살표 함수 구문은 유형 주석을 지원하지 않습니다.

신호 사용에 대한 자세한 내용은 ‘신호 및 핸들러 이벤트 시스템’을 참조하십시오.

속성 변경 신호 핸들러

속성 변경 신호의 신호 핸들러는 on<Property>Changed 형식을 따르며, 여기서 <Property> 는 속성 이름으로 첫 글자가 대문자입니다. 예를 들어, ` TextInput ` 유형 문서에는 ` textChanged ` 신호에 대한 설명이 없지만, ` TextInput `에 ` text ` 속성이 있으므로 이 신호는 암시적으로 사용할 수 있으며, 따라서 이 속성이 변경될 때마다 호출되는 ` onTextChanged ` 신호 핸들러를 작성할 수 있습니다:

import QtQuick

TextInput {
    text: "Change this!"

    onTextChanged: console.log(`Text has changed to: ${text}`)
}

메서드 속성

객체 유형의 메서드는 특정 처리를 수행하거나 추가 이벤트를 트리거하기 위해 호출될 수 있는 함수입니다. 메서드는 신호에 연결되어 신호가 발산될 때마다 자동으로 호출되도록 할 수 있습니다. 자세한 내용은 ‘신호 및 핸들러 이벤트 시스템’을 참조하십시오.

메서드 속성 정의

C++에서 타입에 대한 메서드를 정의하려면, 클래스의 함수에 태그를 지정하고 이를 ` Q_INVOKABLE `를 통해 QML 타입 시스템에 등록하거나, 해당 함수를 클래스의 ` Q_SLOT `로 등록하면 됩니다. 또는 다음 구문을 사용하여 QML 문서의 객체 선언에 사용자 정의 메서드를 추가할 수도 있습니다:

function <functionName>([<parameterName>[: <parameterType>][, ...]]) [: <returnType>] { <body> }

QML 타입에 메서드를 추가하여 독립적이고 재사용 가능한 JavaScript 코드 블록을 정의할 수 있습니다. 이러한 메서드는 내부적으로 또는 외부 객체에 의해 호출될 수 있습니다.

시그널과 달리, 메서드 매개변수 유형은 기본적으로 ` var ` 유형으로 설정되므로 별도로 선언할 필요가 없습니다. 그러나 qmlcachegen이 더 높은 성능의 코드를 생성하도록 돕고 유지보수성을 높이기 위해 매개변수 유형을 선언하는 것이 좋습니다.

동일한 타입 블록 내에서 동일한 이름을 가진 두 개의 메서드나 시그널을 선언하려고 하면 오류가 발생합니다. 그러나 새로운 메서드는 해당 타입에 이미 존재하는 메서드의 이름을 재사용할 수 있습니다. (기존 메서드가 숨겨져 접근할 수 없게 될 수 있으므로, 이 경우 주의해서 진행해야 합니다.)

다음은 height 값을 할당할 때 호출되는 calculateHeight() 메서드를 가진 Rectangle 입니다:

import QtQuick
Rectangle {
    id: rect

    function calculateHeight(): real {
        return rect.width / 2;
    }

    width: 100
    height: calculateHeight()
}

메서드에 매개변수가 있는 경우, 메서드 내부에서는 이름으로 해당 매개변수에 접근할 수 있습니다. 아래 예시에서 MouseArea 을 클릭하면 moveTo() 메서드가 호출되며, 이 메서드는 전달받은 newX 및 newY 매개변수를 참조하여 텍스트의 위치를 조정할 수 있습니다:

import QtQuick

Item {
    width: 200; height: 200

    MouseArea {
        anchors.fill: parent
        onClicked: mouse => label.moveTo(mouse.x, mouse.y)
    }

    Text {
        id: label

        function moveTo(newX: real, newY: real) {
            label.x = newX;
            label.y = newY;
        }

        text: "Move me!"
    }
}

부착된 속성 및 부착된 신호 핸들러

부착 속성과 부착 신호 핸들러는 객체에 본래는 사용할 수 없는 추가 속성이나 신호 핸들러를 부여할 수 있게 해주는 메커니즘입니다. 특히, 이를 통해 객체는 해당 객체와 직접적으로 관련된 속성이나 신호에 접근할 수 있습니다.

QML 타입 구현체는 특정 속성과 신호를 가진 부착 타입을 C++로 생성할 수 있습니다. 그런 다음 런타임 시 이 타입의 인스턴스를 생성하여 특정 객체에 부착함으로써, 해당 객체가 부착 타입의 속성과 신호에 접근할 수 있게 됩니다. 이러한 속성과 신호 핸들러에 접근하려면 해당 속성과 신호 핸들러 이름 앞에 부착 타입의 이름을 접두사로 붙여야 합니다.

부착된 속성 및 핸들러에 대한 참조는 다음과 같은 구문 형식을 따릅니다:

<AttachingType>.<propertyName>
<AttachingType>.on<SignalName>

예를 들어, ` ListView ` 유형에는 ` ListView` 내의 각 델리게이트 객체가 사용할 수 있는 ` ListView.isCurrentItem `라는 부착 속성이 있습니다. 각 개별 델리게이트 객체는 이를 사용하여 자신이 뷰에서 현재 선택된 항목인지 여부를 판단할 수 있습니다:

import QtQuick

ListView {
    width: 240; height: 320
    model: 3
    delegate: Rectangle {
        width: 100; height: 30
        color: ListView.isCurrentItem ? "red" : "yellow"
    }
}

이 경우, 부착된 타입의 이름은 ` ListView `이며, 해당 속성은 ` isCurrentItem`이므로, 부착된 속성은 ` ListView.isCurrentItem`로 지칭됩니다.

부착된 신호 핸들러도 동일한 방식으로 참조됩니다. 예를 들어, ` Component.onCompleted ` 부착 신호 핸들러는 일반적으로 컴포넌트의 생성 과정이 완료되었을 때 일부 JavaScript 코드를 실행하는 데 사용됩니다. 아래 예제에서 ` ListModel `이 완전히 생성되면, 해당 ` Component.onCompleted ` 신호 핸들러가 자동으로 호출되어 모델에 데이터를 채웁니다:

import QtQuick

ListView {
    width: 240; height: 320
    model: ListModel {
        id: listModel
        Component.onCompleted: {
            for (let i = 0; i < 10; i++) {
                append({ Name: `Item ${i}` })
            }
        }
    }
    delegate: Text { text: index }
}

부착된 타입의 이름이 ` Component `이고, 해당 타입에 ` completed ` 신호가 있으므로, 부착된 신호 핸들러는 ` Component.onCompleted`이라고 합니다.

부착된 속성 및 시그널 핸들러에 대한 참고 사항

흔히 발생하는 오류 중 하나는 부착된 속성과 신호 핸들러가 이러한 속성이 부착된 객체의 자식 객체에서 직접 접근할 수 있다고 가정하는 것입니다. 하지만 사실은 그렇지 않습니다. 부착 유형의 인스턴스는 특정 객체에만 부착되며, 해당 객체와 그 모든 자식 객체에 부착되는 것은 아닙니다.

예를 들어, 다음은 부착된 속성과 관련된 앞서 살펴본 예제를 수정한 것입니다. 이번에는 델리게이트가 ` Item `이고, 색상이 지정된 ` Rectangle `가 해당 항목의 자식입니다:

import QtQuick

ListView {
    width: 240; height: 320
    model: 3
    delegate: Item {
        width: 100; height: 30

        Rectangle {
            width: 100; height: 30
            color: ListView.isCurrentItem ? "red" : "yellow" // WRONG! This won't work.
        }
    }
}

ListView.isCurrentItem 는 루트 델리게이트 객체에만 연결되어 있고 자식 객체에는 연결되어 있지 않기 때문에, 이 코드는 예상대로 작동하지 않습니다. Rectangle 는 델리게이트 자체가 아니라 델리게이트의 자식이기 때문에, isCurrentItem 연결 속성에 ListView.isCurrentItem 로 접근할 수 없습니다. 따라서 사각형은 루트 델리게이트를 통해 isCurrentItem 에 접근해야 합니다:

ListView {
    delegate: Item {
        id: delegateItem
        width: 100; height: 30

        Rectangle {
            width: 100; height: 30
            color: delegateItem.ListView.isCurrentItem ? "red" : "yellow" // correct
        }
    }
}

이제 delegateItem.ListView.isCurrentItem 는 델리게이트의 isCurrentItem 부착 속성을 올바르게 참조합니다.

열거형 속성

열거형은 이름이 지정된 고정된 선택 집합을 제공합니다. QML에서는 enum 키워드를 사용하여 이를 선언할 수 있습니다:

// MyText.qml
Text {
    enum TextType {
        Normal,
        Heading
    }
}

위에서 볼 수 있듯이, 열거형 유형(예: TextType)과 값(예: Normal)은 대문자로 시작해야 합니다.

값은 <Type>.<EnumerationType>.<Value> 또는 <Type>.<Value> 형태로 참조합니다.

// MyText.qml
Text {
    enum TextType {
        Normal,
        Heading
    }

    property int textType: MyText.TextType.Normal

    font.bold: textType === MyText.TextType.Heading
    font.pixelSize: textType === MyText.TextType.Heading ? 24 : 12
}

QML에서 열거형의 사용법에 대한 자세한 내용은 QML 열거형 문서를 참조하십시오.

Qt Qml에서 열거형을 선언하는 기능은 Qt 5.10에서 도입되었습니다.

© 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.