このページでは

C

Qt Quick Ultraliteのモデルとビュー

Qt Quick 、データを表示するためのモデルビューデリゲートという概念があります。これらは、開発者や設計者がデータのさまざまな側面を制御できるように、データの視覚化をモジュール化しています。開発者は、データにほとんど変更を加えることなく、リスト・ビューとグリッド・ビューを入れ替えることができる。同様に、デリゲートにデータのインスタンスをカプセル化することで、開発者はデータの表示方法や処理方法を指定することができます。

  • モデル- データとその構造を含む。モデルを作成する方法はいくつかあります。
  • ビュー- データを表示するコンテナ。ビューはデータをリストやグリッドで表示します。
  • デリゲート- データがどのようにビューに表示されるかを指定します。デリゲートはモデル内の各データを受け取り、カプセル化します。データはデリゲートを通してアクセスできます。デリゲートは、編集可能なモデルにデータを書き戻すこともできます。

データを視覚化するには、ビューのmodel プロパティをモデルに、delegate プロパティをコンポーネントまたは他の互換性のある型にバインドします。

ビューによるデータの表示

ビューは、アイテムのコレクションを格納するコンテナです。ビューは機能が豊富で、スタイルや動作の要件に合わせてカスタマイズすることができます。

Qt Quick グラフィカル・タイプの基本セットには、標準的なビューのセットが用意されています:

  • Repeater - あらかじめ決められたレイアウトなしで、データ入力ごとに項目を作成します。
  • ListView - 水平または垂直のリストに項目を並べる

これらのタイプには、それぞれのタイプ専用のプロパティと動作があります。詳細はそれぞれのドキュメントを参照してください。

ビューデリゲート

ビューは、リスト内の項目を視覚的に表現するためにデリゲートを必要とします。ビューは、デリゲートによって定義されたテンプレートに従って、各アイテムのリストを視覚化します。モデル内のアイテムは、アイテムのプロパティと同様に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に設定されることに注意してください。indexロールにバインドする場合は、indexが-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 とは異なり、ListModelListElement は読み取り専用です。つまり、このようなモデルに格納された値を変更することはできません。編集可能なモデルが必要な場合は、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 のプロパティはモデル構造を記述します。

これにより、モデルデータを外部で設定したり、PropertyChanges State で設定したりすることができる。

// 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
        }
    }
}
// NameAgeType.qml
QtObject {
    property string name
    property int age
}
// 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
    }

}

注釈 整数モデルの項目数の上限は、100,000,000 です。

C++データモデル

モデルは C++ で定義し、QML で利用することができます。この仕組みは、既存のC++データモデルやミュータブルなデータセット、 あるいは複雑なデータセットをQMLに公開するのに便利です。

詳しくは、Qul::ListModel およびC++ コードと QML の統合 をご覧ください。


Qt の特定のライセンスの下で利用可能です。