QML オブジェクトの属性

すべての QML オブジェクトタイプには、定義された属性のセットがあります。各オブジェクトのインスタンスは、そのオブジェクトタイプに定義された属性の セットとともに生成されます。属性にはいくつかの種類があり、以下に説明します。

オブジェクト宣言における属性

QML 文書のオブジェクト宣言は、新しい型を定義します。また、新しく定義された型のインスタンスが生成された場合に、インスタンス化されるオブジェクト階層も宣言されます。

QML のオブジェクト型の属性は以下の通りです:

  • id属性
  • property 属性
  • シグナル属性
  • シグナルハンドラ属性
  • メソッド属性
  • アタッチド・プロパティとアタッチド・シグナル・ハンドラ属性
  • 列挙属性

これらの属性の詳細は後述する。

id属性

すべての QML オブジェクト型は、id属性を1つだけ持ちます。この属性は、QML 言語が提供するものであり、どの QML オブジェクト型でも再定義したり、上書きしたりすることはできません。

オブジェクトのインスタンスのid属性には、そのオブジェクトを識別したり、他の オブジェクトから参照したりするための値を指定することができます。このid は、小文字かアンダースコアで始まり、文字、数字、アンダースコア以外の文字を含むことはできません。

以下は、TextInput オブジェクトとText オブジェクトです。TextInput オブジェクトのid 値は "myTextInput "に設定されている。Text オブジェクトは、TextInputtext プロパティと同じ値を持つように、myTextInput.text を参照してtext プロパティを設定します:

import QtQuick

Column {
    width: 200; height: 200

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

    Text { text: myTextInput.text }
}

オブジェクトは、それが宣言されたコンポーネント・スコープ内のどこからでも、id によって参照することができます。したがって、id の値は、そのコンポーネント・スコープ内で常に一意でなければなりません。詳しくは「スコープと命名解決」を参照してください。

オブジェクトのインスタンスが生成されると、そのid属性の値は変更できません。一見普通のプロパティのように見えますが、id 属性は普通のproperty 属性ではなく、特別なセマンティクスが適用されます。例えば、上記の例ではmyTextInput.id にアクセスすることはできません。

プロパティ属性

プロパティはオブジェクトの属性で、静的な値を割り当てることも、動的な式にバインドすることもできます。プロパティの値は、他のオブジェクトから読み取ることができます。ただし、特定の QML タイプがそのプロパティを明示的に禁止している場合を除きます。

プロパティの属性の定義

プロパティは C++ の型に対して定義することができます。そのためには、QML の型システムに登録されたクラスのQ_PROPERTY を登録します。また、オブジェクト型のカスタムプロパティは、QML文書のオブジェクト宣言の中で、以下のような構文で定義することもできます:

[default] [required] [readonly] property <propertyType> <propertyName>

このようにすることで、オブジェクト宣言は特定の値を外部のオブジェクトに公開したり、内部状態をより簡単に保持したりすることができます。

プロパティ名は小文字で始まり、アルファベット、数字、アンダースコアのみを含むことができます。JavaScriptの予約語は有効なプロパティ名ではありません。default,required,readonly キーワードはオプションで、宣言されているプロパティのセマンティクスを変更します。それぞれの意味についての詳細は、デフォルト・プロパティ必須プロパティ読み取り専用プロパティの項を参照してください。

カスタムプロパティを宣言すると、そのプロパティの値変更シグナルが暗黙のうちに作成され、on <PropertyName >Changedと呼ばれる関連シグナルハンドラも作成されます。

例えば、次のオブジェクト宣言では、Rectangle基本型から派生した新しい型を定義しています。これには2つの新しいプロパティがあり、そのうちの1つの新しいプロパティに対してシグナル・ハンドラが実装されています:

Rectangle {
    property color previousColor
    property color nextColor
    onNextColorChanged: console.log("The next color will be: " + nextColor.toString())
}
カスタムプロパティ定義で有効な型

enumeration 型以外のQML の値型は、カスタムプロパティの型として使用することができます。例えば、これらはすべて有効なプロパティ宣言です:

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

(列挙値は単に整数の値であり、int 型で参照することができます)。

いくつかの値型はQtQuick モジュールによって提供されているため、そのモジュールをインポートしない限り、プロパティ型として使用することはできません。詳しくはQML Value Typesを参照してください。

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型にも当てはまります。あるQMLの型がColorfulButton.qml (クライアントがインポートしたディレクトリ)という名前のファイルで定義されていた場合、ColorfulButton という型のプロパティも有効です。

プロパティ属性への値の割り当て

オブジェクト・インスタンスのプロパティの値は、2つの方法で指定することができます:

  • 初期化時の値の割り当て
  • 命令的な値の割り当て

どちらの場合も、値は静的な値かバインディング式の値のどちらかになります。

初期化時の値の割り当て

初期化時にプロパティに値を代入する構文は次のとおりです:

<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"
    }
}

静的値と結合式値

前述したように、プロパティに代入できる値には静的な値と結合式の値の2種類があります。後者はプロパティ・バインディングとしても知られています。

種類セマンティクス
静的値他のプロパティに依存しない定数値。
バインディング式プロパティの他のプロパティとの関係を記述する 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() は、初期化時にバインディング式を代入する場合には使用してはいけません。詳しくはプロパティ・バインディングを参照してください。

型の安全性

プロパティは型安全です。プロパティには、プロパティの型に一致する値しか割り当てることができません。

例えば、プロパティがrealの場合、それに文字列を代入しようとするとエラーになります:

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 型にはstates プロパティがあり、これはState 型のオブジェクトのリストを保持するために使われます。以下のコードは、このプロパティの値を3つの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 プロパティを宣言してください。

グループ化されたプロパティ

場合によっては、プロパティは論理的なサブプロパティ属性のグループを含みます。これらのサブプロパティ属性は、ドット記法かグループ記法のどちらかを使って割り当てることができます。

例えば、Text 型には、font グループ・プロパティがあります。以下では、最初のText オブジェクトはドット記法を用いてfont の値を初期化し、2 番目のオブジェクトはグループ記法を用いています:

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

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

グループ化されたプロパティ型は、サブプロパティを持つ型です。グループ化されたプロパティ型が(値型ではなく)オブジェクト型の場合、それを保持するプロパティは読み取り専用でなければなりません。これは、サブプロパティが属するオブジェクトを置き換えることを防ぐためです。

プロパティのエイリアス

プロパティのエイリアスは、別のプロパティへの参照を保持するプロパティです。プロパティのために新しくユニークな記憶領域を確保する通常のプロパティ定義とは異なり、プロパティ・エイリアスは、新しく宣言されたプロパティ(エイリアス・プロパティと呼ばれる)を既存のプロパティ(エイリアス・プロパティ)への直接参照として接続します。

プロパティ・エイリアス宣言は、プロパティ型の代わりにalias キーワードを必要とすることと、プロパティ宣言の右辺が有効なエイリアス参照でなければならないことを除けば、普通のプロパティ定義と同じように見えます:

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

通常のプロパティとは異なり、エイリアスには以下の制限があります:

  • エイリアスが宣言された型のスコープ内にあるオブジェクト、またはオブジェクトのプロパティのみを参照することができます。
  • 任意のJavaScript式を含むことはできない。
  • その型のスコープ外で宣言されたオブジェクトを参照することはできません。
  • エイリアスの参照は、通常のプロパティのオプションのデフォルト値とは異なり、オプションではありません。
  • エイリアス参照は、エイリアスが最初に宣言されたときに提供されなければなりません
  • 深さ3以上の階層内のプロパティを参照することはできません。以下のコードは動作しません:
    property alias color: myItem.myRect.border.color
    
    Item {
        id: myItem
        property Rectangle myRect
    }

    ただし、深さ2レベルまでのプロパティへのエイリアスは動作します。

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

例えば、Text の子のtext オブジェクトに接続されているbuttonText エイリアスされたプロパティを持つButton タイプがあります:

// 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 の値は変更されるでしょうが、その逆はありえません。

プ ロパテ ィ エイリアスに関する考察

エイリアスプロパティが既存のプロパティと同じ名前を持つことは可能であり、事実上、既存のプロパティを上書きすることになります。例えば、以下のQML型はcolor エイリアスプロパティを持っており、組み込みのRectangle::color プロパティと同じ名前になっています:

Rectangle {
    id: coloredrectangle
    property alias color: bluerectangle.color
    color: "red"

    Rectangle {
        id: bluerectangle
        color: "#1234ff"
    }

    Component.onCompleted: {
        console.log (coloredrectangle.color)    //prints "#1234ff"
        setInternalColor()
        console.log (coloredrectangle.color)    //prints "#111111"
        coloredrectangle.color = "#884646"
        console.log (coloredrectangle.color)    //prints #884646
    }

    //internal function that has access to internal properties
    function setInternalColor() {
        color = "#111111"
    }
}

この型を使用してcolor プロパティを参照するオブジェクトは、通常のRectangle::color プロパティではなく、エイリアスを参照することになります。しかし内部的には、矩形はcolor プロパティを正しく設定し、エイリアスではなく実際に定義されたプロパティを参照することができます。

プロパティ・エイリアスと型

プロパティ・エイリアスは、明示的な型指定を持つことはできません。プロパティ・エイリアスの型は、それが参照するプロパティまたはオブジェクトの宣言された型です。したがって、インラインで宣言された追加プロパティを持つ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
}

しかし、内部オブジェクトを専用の.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
}

デフォルト・プロパティ

オブジェクト定義には、デフォルト・プロパティを1つ持つことができます。デフォルト・プロパティとは、オブジェクトが他のオブジェクトの定義内で、特定のプロパティの値として宣言されずに宣言された場合に、値が割り当てられるプロパティのことです。

オプションのdefault キーワードを使用してプロパティを宣言すると、そのプロパティがデフォルト・プロパティとしてマークされます。例えば、ファイルMyLabel.qmlにデフォルト・プロパティsomeText があるとします:

// MyLabel.qml
import QtQuick

Text {
    default property var someText

    text: `Hello, ${someText.text}`
}

someText の値は、MyLabel オブジェクト定義の中で、このように代入することができます:

MyLabel {
    Text { text: "world!" }
}

これは以下と全く同じ効果を持ちます:

MyLabel {
    someText: Text { text: "world!" }
}

しかし、someText プロパティはデフォルト・プロパティとしてマークされているので、Text オブジェクトを明示的にこのプロパティに割り当てる必要はありません。

子オブジェクトは、children プロパティに明示的に追加することなく、Item ベースの型に追加できることにお気づきでしょう。これは、Item のデフォルト・プロパティがそのdata プロパティであり、Item に対してこのリストに追加された項目は、自動的にそのリストchildren に追加されるからです。

デフォルト・プロパティは、アイテムの子を再割り当てするのに便利です。例えば

Item {
    default property alias content: inner.children

    Item {
        id: inner
    }
}

デフォルト・プロパティのエイリアスを inner.children に設定すると、外側のアイテムの子として割り当てられたオブジェクトは、自動的に内側のアイテムの子として割り当て直されます。

警告 要素のデフォルト・リスト・プロパティの値の設定は、暗黙的または明示的に行うことができます。1つの要素の定義の中で、この2つのメソッドを混在させてはいけません。リスト内の要素の順序が未定義になるからです。

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

必須プロパティ

オブジェクト宣言では、required キーワードを使用して、プロパティを必須として定義することができます。構文は次のとおりです。

required property <propertyType> <propertyName>

その名前が示すように、必須プロパティはオブジェクトのインスタンスが作成されるときに設定されなければなりません。この規則に違反すると、静的に検出された場合、QMLアプリケーションは起動しなくなります。動的にインスタンス化されたQMLコンポーネントの場合(例えばQt.createComponent()など)、このルールに違反すると警告が表示され、NULLが返されます。

で既存のプロパティをrequiredにすることができます。

required <propertyName>

次の例は、color プロパティが常に指定される必要がある、カスタム Rectangle コンポーネントの作成方法を示しています。

// ColorRectangle.qml
Rectangle {
    required color
}

注意: QML から required プロパティに初期値を割り当てることはできません。

必須プロパティは、モデル・ビュー・デリゲートのコードでは特別な役割を果たします:ビューのデリゲートに、ビューのモデルのロール名と一致する名前の必須プロパティがある場合、それらのプロパティはモデルの対応する値で初期化されます。詳細については、Qt Quick の Models and Viewsのページを参照してください。

C++ から必須プロパティーを初期化する方法については、QQmlComponent::createWithInitialPropertiesQQmlApplicationEngine::setInitialPropertiesQQuickView::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 型は、数値型(intreal など)のプロパティのみをアニメーション化します。数値以外のプロパティでNumberAnimation を使おうとしてもエラーにはなりませんが、数値以外のプロパティはアニメートされません。特定のプロパティタイプに関連付けられたときのプロパティ修飾タイプの動作は、その実装によって定義されます。

シグナルの属性

たとえば、プロパティが変更されたとき、アニメーションが開始または停止したとき、画像がダウンロードされたときなどです。例えば、MouseArea 型には、clicked シグナルがあり、ユーザーがマウス領域内をクリックしたときに発信されます。

特定のシグナルが発せられると、シグナル・ハンドラを通してオブジェクトに通知することができる。シグナル・ハンドラはon<Signal>という構文で宣言します。シグナルハンドラは、シグナルを発するオブジェクトの定義内で宣言されなければなりません。また、シグナルハンドラが呼び出されたときに実行されるJavaScriptコードのブロックを含んでいなければなりません。

例えば、以下のonClickedシグナル・ハンドラは、MouseArea オブジェクト定義内で宣言され、MouseArea がクリックされると起動され、コンソール・メッセージが出力されます:

import QtQuick

Item {
    width: 100; height: 100

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

シグナル属性の定義

C++の型に対してシグナルを定義するには、QMLの型システムに登録されている クラスのQ_SIGNAL 。あるいは、QML文書中のオブジェクト宣言の中で、次のような構文でオブジェクト型のカスタムシグナルを定義することもできます:

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

同じ型ブロックの中で同じ名前のシグナルやメソッドを2つ宣言しようとするとエラーになります。しかし、新しいシグナルはその型に存在するシグナルの名前を再利用することができます。(この場合、既存のシグナルが隠されてアクセスできなくなる可能性があるため、注意が必要です)。

以下はシグナル宣言の3つの例です:

import QtQuick

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

シグナルのパラメータは、propertyスタイルの構文で指定することもできます:

signal actionCanceled(string action)

メソッド宣言との一貫性を保つため、型宣言はコロンで囲むようにしましょう。

シグナルにパラメータがない場合、"() "カッコは省略可能です。パラメータを使用する場合は、上記のactionPerformed シグナルの引数stringint のように、パラメータの型を宣言する必要があります。使用可能なパラメータ・タイプは、このページの「プロパティ属性の定義」に記載されているものと同じです。

シグナルを発信するには、それをメソッドとして呼び出します。シグナルが発信されると、関連するシグナルハンドラが呼び出され、ハンドラは定義されたシグナルの引数名を使用して、それぞれの引数にアクセスすることができます。

プロパティ変更シグナル

QMLの型にはプロパティ変更シグナルも組み込まれており、プロパティの値が変更されたときに発信されます。これらのシグナルがなぜ有用なのか、また、どのように使用するのかについては、プロパティ変更シグナルハンドラのセクションを参照してください。

シグナルハンドラの属性

シグナルハンドラは特殊なメソッド属性であり、シグナルが発せられるたびに QML エンジンがそのメソッドの実装を呼び出します。QMLのオブジェクト定義にシグナルを追加すると、自動的に関連するシグナルハンドラが追加されます。クライアントはプログラムロジックを実装するための実装を提供することができます。

次のようなSquareButton 型を考えてみましょう。SquareButton.qml ファイルに定義があり、activateddeactivated というシグナルがあります:

// 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<プロパティ>Changedという構文をとります。例えば、TextInput 型のドキュメントにはtextChanged シグナルは記述されていませんが、TextInputtext プロパティを持っていることから、このシグナルは暗黙のうちに利用可能であり、このプロパティが変更されるたびに呼び出されるonTextChanged シグナル・ハンドラを記述することが可能です:

import QtQuick

TextInput {
    text: "Change this!"

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

メソッド属性

オブジェクト型のメソッドは、何らかの処理を実行したり、さらなるイベントをトリガーしたりするために呼び出される関数です。メソッドはシグナルに接続することができ、シグナルが発信されるたびに自動的に呼び出されます。詳しくはシグナルとハンドラのイベントシステムを参照してください。

メソッド属性の定義

メソッドは C++ の型に対して、QML の型システム(Q_INVOKABLE )に登録された クラスの関数にタグを付けるか、クラスのQ_SLOT として登録することで定義することができます。また、QML文書中のオブジェクト宣言に以下のような構文でカスタムメソッドを追加することもできます:

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

メソッドをQMLの型に追加することで、再利用可能な独立したJavaScriptコードのブロックを定義することができます。メソッドを QML 型に追加することで、スタンドアロンで再利用可能な JavaScript のコードブロックを定義することができます。

シグナルとは異なり、メソッドのパラメータ型はデフォルトでvar の型となるため、宣言する必要はありません。しかし、qmlcachegen がよりパフォーマンスの高いコードを生成し、保守性を向上させるためには、宣言する必要があります。

同じ型ブロック内で同じ名前の 2 つのメソッドまたはシグナルを宣言しようとするとエラーになります。ただし、新しいメソッドは、型に既存のメソッドの名前を再利用することができます。(この場合、既存のメソッドが隠されてアクセスできなくなる可能性があるため、注意が必要である)。

以下は、height の値を代入するときに呼び出されるcalculateHeight() メソッドを持つRectangle です:

import QtQuick
Rectangle {
    id: rect

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

    width: 100
    height: calculateHeight()
}

メソッドにパラメータがある場合は、メソッド内でパラメータ名にアクセスできます。以下では、MouseArea がクリックされると、moveTo() メソッドが呼び出され、受け取ったnewXnewY パラメータを参照してテキストの位置を変更することができます:

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 Value Types enumeration のドキュメントを参照してください。

QML で列挙型を宣言する機能は Qt 5.10 で導入されました。

©2024 The Qt Company Ltd. 本ドキュメントに含まれる文書の著作権は、それぞれの所有者に帰属します。 ここで提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。