C
Qt Quick Ultraliteにおけるモデルとビュー
アプリケーションでは、データの提供や表示が必要になることがよくあります。Qt Quick では、データを表示するために「モデル」「ビュー」「デリゲート」という概念が用いられています。これらはデータの可視化をモジュール化することで、開発者やデザイナーがデータのさまざまな側面を制御できるようにします。 開発者は、データにほとんど変更を加えることなく、リストビューをグリッドビューに置き換えることができます。同様に、データのインスタンスをデリゲートにカプセル化することで、開発者はデータの表示方法や処理方法を指定できるようになります。

- モデル- データとその構造を保持します。モデルを作成する方法はいくつかあります。
- ビュー- データを表示するコンテナです。ビューは、データをリスト形式やグリッド形式で表示することがあります。
- デリゲート- データがビューにどのように表示されるかを決定します。デリゲートはモデル内の各データを取得してカプセル化します。データへのアクセスはデリゲートを介して行われます。また、デリゲートは編集可能なモデルにデータを書き戻すこともできます。
データを可視化するには、ビューのmodel プロパティをモデルにバインドし、delegate プロパティをコンポーネントまたは他の互換性のある型にバインドします。
ビューによるデータの表示
ビューは、項目のコレクションを格納するコンテナです。豊富な機能を備えており、スタイルや動作の要件に合わせてカスタマイズすることができます。
Qt Quick の基本的なグラフィカルタイプには、一連の標準ビューが用意されています:
これらのタイプには、それぞれ固有のプロパティや動作があります。詳細については、各タイプのドキュメントを参照してください。
ビューのデリゲート
ビューは、リスト内の項目を視覚的に表現するためにデリゲートを必要とします。ビューは、デリゲートによって定義されたテンプレートに従って、各項目リストを可視化します。モデル内の項目には、index プロパティおよび項目のプロパティを通じてアクセスできます。
Component {
id: petdelegate
Text {
id: label
width: view.width / petlist.count
height: view.height / petlist.count
font.pixelSize: 24
text: if (index == 0)
label.text = model.type + " (default)"
else
text: model.type
}
}
モデル
データは、名前付きデータロールを通じてデリゲートに提供され、デリゲートはこれらにバインドすることができます。以下は、typeとageという2つのロールを持つListModel と、これらのロールにバインドしてその値を表示するデリゲートを持つListView の例です。
import QtQuick 2.15
Rectangle {
color: "white"
ListModel {
id: myModel
ListElement {
type: "Dog"
age: 8
}
ListElement {
type: "Cat"
age: 5
}
}
Component {
id: myDelegate
Text {
width: listView.width / myModel.count
height: listView.height / myModel.count
text: model.type + ", " + model.age
}
}
ListView {
id: listView
anchors.fill: parent
model: myModel
delegate: myDelegate
}
}どのロールにアクセスできるかを制御し、デリゲートをより自己完結型にしてビューの外でも利用できるようにするには、必須プロパティを使用できます。 デリゲートに必須プロパティが含まれている場合、名前付きロールは提供されません。その代わりに、Qt Quick Ultraliteエンジンは、必須プロパティの名前がモデルのロール名と一致するかどうかを確認します。一致する場合、そのプロパティはモデルからの対応する値にバインドされます。
import QtQuick 2.15
Rectangle {
color: "white"
ListModel {
id: myModel
ListElement {
type: "Dog"
age: 8
noise: "meow"
}
ListElement {
type: "Cat"
age: 5
noise: "woof"
}
}
Component {
id: delegate
Text {
width: listView.width / myModel.count
height: listView.height / myModel.count
required property string type
required property int age
text: type + ", " + age
// WRONG: text: type + ", " + noise
// The above line would cause a compiler error
// as there is no required property noise
}
}
ListView {
id: listView
anchors.fill: parent
model: myModel
delegate: delegate
}
}モデルのプロパティとデリゲートのプロパティの間で命名上の競合がある場合、代わりに修飾されたモデル名を使用してロールにアクセスできます。 たとえば、Text 型に`type`プロパティと`age` プロパティがある場合、上記の例では、モデルからの`type`および`age`の値ではなく、これらのプロパティの値が表示されます。この場合、デリゲートがモデルからのプロパティ値を確実に表示するようにするには、代わりに `model.type ` および `model.age ` としてプロパティを参照すればよかったことになります。
また、デリゲートでは、モデル内の項目のインデックスを含む特別なインデックスロールも利用可能です。なお、項目がモデルから削除された場合、このインデックスは -1 に設定されることに注意してください。 インデックスロールにバインドする場合は、インデックスが -1 になる可能性、つまりそのアイテムがもはや有効ではない可能性をロジックで考慮するようにしてください。通常、そのアイテムはまもなく破棄されますが、一部のビューではデリゲートの破棄を遅延させることも可能です。
名前付きロールを持たないモデルでは、データはmodelDataロールを介して提供されます。modelDataロールは、ロールが 1 つしかないモデルにも提供されます。この場合、modelDataロールには、名前付きロールと同じデータが含まれます。
注: デリゲートに必須プロパティが含まれている場合、index およびmodelDataロールにはアクセスできません。ただし、デリゲート側に同じ名前の必須プロパティが存在する場合はこの限りではありません。
リストモデル
ListModel は、QMLで指定される単純な型の階層構造です。利用可能なロールは、ListElement プロパティによって指定されます。
ListModel {
id: fruitModel
ListElement {
name: "Apple"
cost: 245
}
ListElement {
name: "Orange"
cost: 325
}
ListElement {
name: "Banana"
cost: 195
}
}上記のモデルには、nameとcostの2つのロールがあります。これらは、ListView デリゲートによってバインドすることができます。例えば、次のようにします。
ListView {
anchors.fill: parent
model: fruitModel
delegate: Row {
width: parent.width / fruitModel.count
height: parent.height / fruitModel.count
Text { text: "Fruit: " + model.name }
Text { text: " Cost: $" + model.cost }
}
}注: Qt Quickとは異なり 、ListModel およびListElement は読み取り専用です。つまり、このようなモデルに格納された値を変更することはできません。編集可能なモデルが必要な場合は、「Qul::ListModel 」および「C++コードとQMLの統合」を参照してください。
オブジェクトのリスト
オブジェクトリテラルを含む配列リテラルをモデルとして使用できます。配列の現在の要素は、modelData ロールとして利用可能であり、直接、またはmodel.modelData としてアクセスできます。
ListView {
anchors.fill: parent
model: [
{ name: "Apple", color: "green" },
{ name: "Pear", color: "pink" }
]
delegate: Row {
width: parent.width / 2
height: parent.height / 2
Text { text: "Fruit: " + modelData.name }
Text { text: " Color: " + model.modelData.color }
}
}ListModel<T>型のプロパティ
ListModel<T> 型のプロパティをモデルとして使用できます。この場合、T のプロパティがモデルの構造を記述します。
これにより、モデルデータは外部から、あるいはState 内のPropertyChanges によって設定することが可能になります。
// MyView.qml
Item {
width: 120
height: 40
property ListModel<NameAgeType> myModel
ListView {
anchors.fill: parents
model: myModel
delegate: Text {
width: parent.width / myModel.count
height: parent.height / myModel.count
text: model.name
}
}
}// User.qml
Rectangle {
Row {
MyView {
myModel: [{ name: "John Smith", age: 42 }]
}
MyView {
myModel: ListModel { ListElement { name: "Smith"; age: 42 } }
}
}
}注: ListModel<T> 型は Qt Quick Ultraliteに固有のものであり、Qt Quick には存在しません。これを使用すると、QMLコードはQt Quick と互換性がなくなります。これを使用しない場合、別のファイルでモデルを宣言することはできません。
モデルとしての整数
整数は、特定の数の型を含むモデルとして使用できます。この場合、モデルにはデータロールは存在しません。
次の例では、5つの要素を持つListView を作成しています:
Rectangle {
Component {
id: itemDelegate
Text {
width: listView.width / 5
height: listView.height / 5
text: "I am item number: " + index
}
}
ListView {
id: listView
anchors.fill: parent
model: 5
delegate: itemDelegate
}
}注: 整数モデルに含まれる項目の数には、1億という上限があります。
C++ データモデル
モデルはC++で定義し、QMLから利用できるようにすることができます。この仕組みは、既存のC++データモデルや、変更可能なデータセット、あるいはその他の複雑なデータセットをQMLに公開する際に役立ちます。
詳細については、「Qul::ListModel 」および「C++コードとQMLの統合」をご覧ください。
特定の Qt ライセンスの下で利用可能です。
詳細はこちらをご覧ください。