QML オブジェクトの属性
すべての QML オブジェクト型には、定義済みの属性セットがあります。オブジェクト型の各インスタンスは、そのオブジェクト型に対して定義された属性セットを持って作成されます。指定可能な属性にはいくつかの種類があり、以下で説明します。
オブジェクト宣言における属性
QMLドキュメント内のオブジェクト宣言は、新しい型を定義します。また、その新しく定義された型のインスタンスが作成された場合にインスタンス化されるオブジェクト階層も宣言します。
QML オブジェクト型の属性タイプは以下の通りです:
- id属性
- プロパティ属性
- シグナル属性
- シグナルハンドラ属性
- メソッド属性
- アタッチされたプロパティおよびアタッチされたシグナルハンドラ属性
- 列挙型の属性
これらの属性については、以下で詳しく説明します。
id属性
QML 要素は、id属性を最大 1 つまで持つことができます。この属性は言語自体によって提供されるものであり、いかなる 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 の値は、そのコンテキスト内で常に一意でなければなりません。詳細については、「スコープと名前解決」を参照してください。
このコンテキストは、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>このようにして、オブジェクト宣言は特定の値を外部オブジェクトに公開したり、内部状態をより容易に管理したりすることができます。
プロパティ名は小文字で始まり、文字、数字、アンダースコアのみを含めることができます。JavaScriptの予約語は有効なプロパティ名にはなりません。default 、required 、readonly 、virtual 、override 、final というキーワードはオプションであり、宣言されるプロパティの意味論を変更します。 それぞれの意味に関する詳細については、後述する「デフォルトプロパティ」、「必須プロパティ」、「読み取り専用プロパティ」、および「オーバーライドのセマンティクス」に関するセクションを参照してください。
カスタムプロパティを宣言すると、そのプロパティに対する値変更シグナルが暗黙的に作成されるほか、on<PropertyName>Changed という関連するシグナルハンドラも作成されます。ここで、<PropertyName>はプロパティ名であり、最初の文字は大文字になります。
たとえば、次のオブジェクト宣言は、Rectangle 基底型から派生する新しい型を定義しています。この型には 2 つの新しいプロパティがあり、そのうちの 1 つに対してシグナルハンドラが実装されています。
Rectangle {
property color previousColor
property color nextColor
onNextColorChanged: console.log("The next color will be: " + nextColor.toString())
}カスタムプロパティ定義で使用可能な型
QMLの値型であれば、いずれもカスタムプロパティの型として使用できます。たとえば、以下はすべて有効なプロパティ宣言です:
(列挙型の値は単なる整数値であり、代わりに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 型のプロパティも有効となります。
プロパティ属性への値の割り当て
オブジェクトインスタンスのプロパティの値は、次の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()が返す値をプロパティに代入する必要があります。対照的に、初期化時にバインディング式を代入する場合は、 ()を使用してはなりません。詳細については、「プロパティのバインディング」を参照してください。
型安全性
プロパティは型安全です。プロパティには、そのプロパティの型と一致する値のみを代入できます。
たとえば、プロパティが 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 プロパティがあります。以下のコードは、このプロパティの値を3つのState オブジェクトのリストに初期化しています:
import QtQuick
Item {
states: [
State { name: "loading" },
State { name: "running" },
State { name: "stopped" }
]
}リストに要素が1つだけ含まれる場合は、角括弧を省略できます:
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.bold: true
}
Text {
//group notation
font { pixelSize: 12; bold: true }
}グループ化されたプロパティ構文は、その型自体がサブプロパティを持つあらゆるプロパティで使用可能です。これは単なる表記法であり、別の種類のプロパティというわけではありません。プロパティが `font ` のような値型を保持しているか、オブジェクト型を保持しているかによって、構文に違いは生じません。
ただし、プロパティの型はエンジンが実行すべき処理に影響を与えます:
- プロパティが値型を保持している場合、エンジンはその値を読み取り、変更を加え、書き戻します。したがって、そのプロパティは書き込み可能でなければなりません。
- プロパティが値型を保持している場合、代入操作はプロパティが現在保持しているオブジェクトに対して行われます。代入操作が適用される際、そのオブジェクトはnullであってはなりません。 プロパティ自体は読み取り専用でも書き込み可能でもかまいません。読み取り専用に設定することは、QML コードがサブプロパティが属するオブジェクトを置き換えてしまうのを防ぎ、グループ化されたプロパティがどのオブジェクトに適用されるかという混乱を避けるための方法です。これは一般的に推奨される手法です。
サブプロパティ名は、実行時にそのプロパティが保持しているオブジェクトの型ではなく、プロパティの宣言された型に基づいて解決されます。また、同じオブジェクト定義内で同じプロパティに対して両方の形式を使用することはできません。つまり、プロパティにオブジェクトを割り当てるか、そのサブプロパティに値を割り当てるかのいずれか一方のみを行う必要があります。
プロパティエイリアス
プロパティエイリアスとは、別のプロパティへの参照を保持するプロパティのことです。プロパティに対して新しい一意の記憶領域を割り当てる通常のプロパティ定義とは異なり、プロパティエイリアスは、新しく宣言されたプロパティ(エイリアシングプロパティと呼ばれる)を、既存のプロパティ(エイリアスされたプロパティ)への直接参照として結びつけます。
プロパティエイリアスの宣言は、通常のプロパティ定義と似ていますが、プロパティ型の代わりに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 の値も変更されますが、その逆は起こりません。
プロパティのエイリアスと型
プロパティエイリアスには、明示的な型指定を行うことはできません。プロパティエイリアスの型は、それが参照するプロパティまたはオブジェクトの宣言された型となります。したがって、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
}デフォルトのプロパティ
オブジェクト定義には、1つのデフォルトプロパティのみ指定できます。プロパティを指定せずに、あるオブジェクトが別のオブジェクトの直下にネストされている場合、そのオブジェクトは自動的に親オブジェクトのデフォルトプロパティに割り当てられます。
オプションの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 型、object型、およびそれらのシーケンス型のプロパティのみをマークすることが有用です:デフォルトプロパティにはオブジェクトインスタンスのみが割り当てられるため、例えば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 のリストに追加されるためです。
デフォルトプロパティは、アイテムの子要素を再割り当てする際に役立ちます。例えば:
defaultプロパティのエイリアスを inner.children に設定することで、外側の項目の子として割り当てられたオブジェクトは、自動的に内側の項目の子として再割り当てされます。
警告: 要素のデフォルトリストプロパティの値の設定は 、暗黙的または明示的に行うことができます。単一の要素の定義内では、これら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
}オーバーライドのセマンティクス
デフォルトでは、プロパティはシャドウイングされる可能性があります。つまり、派生した QML タイプ内でプロパティを再宣言し、場合によっては新しい型や新しい属性を付与することがあります。その結果、同じ名前のプロパティが 2 つ存在することになりますが、特定のコンテキストではそのうちの 1 つにしかアクセスできません。これは、望ましい結果となることはめったにありません。 多くの場合、これは意図しないものであり、その影響は極めて混乱を招くものです。さらに、シャドウイングはツール開発の妨げとなります。
この問題に対処するため、virtual 、override 、final というキーワードと、追加の警告およびエラーが導入されました。
詳細および警告やエラーを含む包括的な例については、「プロパティのシャドウイングとオーバーライドのセマンティクス」のページを参照してください。
必須のプロパティ
オブジェクト宣言では、required キーワードを使用して、プロパティを必須として定義することができます。構文は次のとおりです。
required property <propertyType> <propertyName>その名前が示す通り、必須プロパティは、オブジェクトのインスタンスが作成される際に設定されなければなりません。このルールに違反すると、静的に検出可能な場合、QML アプリケーションが起動しなくなります。動的にインスタンス化される QML コンポーネント(例えば、Qt.createComponent() を使用する場合)の場合、このルールに違反すると警告が表示され、戻り値は null になります。
既存のプロパティを必須にするには、次のようにします。
required <propertyName>以下の例は、colorプロパティを常に指定する必要があるカスタムRectangleコンポーネントを作成する方法を示しています。
// ColorRectangle.qml
Rectangle {
required color
}注: QML から必須プロパティに初期値を割り当てることは できません。これは、必須プロパティの意図された使用法に直接反するからです。
必須プロパティは、モデル・ビュー・デリゲート(MVD)コードにおいて特別な役割を果たします。ビューのデリゲートに、そのビューのモデルのロール名と一致する名前の必須プロパティがある場合、それらのプロパティはモデルの対応する値で初期化されます。詳細については、「Qt Quick 」ページの「Models and Views」をご覧ください。
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>はシグナルの名前であり、最初の文字は大文字で表記します。 シグナルハンドラは、シグナルを発行するオブジェクトの定義内で宣言する必要があり、ハンドラには、シグナルハンドラが呼び出された際に実行される JavaScript コードのブロックを含める必要があります。
たとえば、以下の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>[, ...]])]同じ型ブロック内で同じ名前のシグナルやメソッドを2つ宣言しようとするとエラーになります。ただし、新しいシグナルは、その型上の既存のシグナルの名前を再利用することができます。(既存のシグナルが非表示になり、アクセスできなくなる可能性があるため、この操作は慎重に行う必要があります。)
以下に、シグナル宣言の3つの例を示します:
import QtQuick
Item {
signal clicked
signal hovered()
signal actionPerformed(action: string, actionResult: int)
}また、プロパティ形式の構文でシグナルのパラメータを指定することもできます:
signal actionCanceled(string action)メソッド宣言との一貫性を保つため、コロン(:)を使用した型宣言を優先すべきです。
シグナルにパラメータがない場合、「()」の括弧は省略可能です。パラメータを使用する場合は、上記のactionPerformed シグナルのstring およびint 引数と同様に、パラメータ型を宣言する必要があります。許可されるパラメータ型は、このページの「プロパティ属性の定義」に記載されているものと同じです。
シグナルを発行するには、それをメソッドとして呼び出します。シグナルが発行されると、関連するシグナルハンドラがすべて呼び出され、ハンドラは定義されたシグナル引数名を使用して、それぞれの引数にアクセスできます。
プロパティ変更シグナル
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がより高性能なコードを生成できるようにし、保守性を高めるためにも、パラメータ型を宣言することを推奨します。
同じタイプブロック内で、同じ名前のメソッドまたはシグナルを2つ宣言しようとするとエラーになります。ただし、新しいメソッドが、そのタイプ上の既存のメソッドの名前を再利用することは可能です。(既存のメソッドが非表示になり、アクセスできなくなる可能性があるため、この操作は慎重に行う必要があります。)
以下は、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.isCurrentItem というアタッチされたプロパティがあり、ListView 内の各デリゲートオブジェクトから利用可能です。これは、個々のデリゲートオブジェクトが、自身がビュー内で現在選択されている項目であるかどうかを判断するために使用できます:
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.