このページでは

ListModel QML Type

自由形式のリストデータソースを定義します。詳細...

Import Statement: import QtQml.Models

プロパティ

方法

  • void append(jsobject dict)
  • void clear()
  • var get(int index)
  • void insert(int index, jsobject dict)
  • void move(int from, int to, int n)
  • void remove(int index, int count)
  • void set(int index, jsobject dict)
  • void setProperty(int index, string property, var value)
  • void sync()

詳細な説明

ListModelは、ListElement 定義の単純なコンテナであり、各定義にはデータロールが含まれています。内容は動的に定義することも、QMLで明示的に定義することもできます。

モデル内の要素数は、count プロパティから取得できます。また、モデルの内容を操作するためのappend()、insert()、move()、remove()、set()など、よく使われるメソッドも提供されています。これらのメソッドは引数として辞書を受け取り、モデルによってListElement オブジェクトに変換されます。

setProperty() メソッドを使用すると、モデルを介して要素を操作でき、指定された要素の役割を設定および変更することができます。

ListModelはQAbstractListModel を継承しており、Q_INVOKABLE といったメソッドを提供しています。例えば、QAbstractItemModel::index を使用することで、行と列に対応するQModelIndex を取得できます。

使用例

次の例は、「name」および「cost」というロールを持つ3つの要素を含むListModelを示しています。

リンゴ、オレンジ、バナナの価格一覧

import QtQuick

ListModel {
    id: fruitModel

    ListElement {
        name: "Apple"
        cost: 2.45
    }
    ListElement {
        name: "Orange"
        cost: 3.25
    }
    ListElement {
        name: "Banana"
        cost: 1.95
    }
}

各要素のロール(プロパティ)は小文字で始まる必要があり、モデル内のすべての要素で共通である必要があります。要素の定義方法に関する詳細なガイドラインは、ListElement のドキュメントに記載されています。

このサンプルモデルにはid プロパティが含まれているため、この例のListView などのビューから参照することができます。

import QtQuick

Rectangle {
    width: 200; height: 200

    ListModel {
        id: fruitModel
        ...
    }

    Component {
        id: fruitDelegate
        Row {
            spacing: 10
            Text { text: name }
            Text { text: '$' + cost }
        }
    }

    ListView {
        anchors.fill: parent
        model: fruitModel
        delegate: fruitDelegate
    }
}

ロールにはリストデータを含めることができます。次の例では、果物の属性のリストを作成します。

ListModel {
    id: fruitModel

    ListElement {
        name: "Apple"
        cost: 2.45
        attributes: [
            ListElement { description: "Core" },
            ListElement { description: "Deciduous" }
        ]
    }
    ListElement {
        name: "Orange"
        cost: 3.25
        attributes: [
            ListElement { description: "Citrus" }
        ]
    }
    ListElement {
        name: "Banana"
        cost: 1.95
        attributes: [
            ListElement { description: "Tropical" },
            ListElement { description: "Seedless" }
        ]
    }
}

このデリゲートは、すべての果物の属性を表示します:

ネストされた属性データを持つ果物を一覧表示するリスト

Component {
    id: fruitDelegate
    Item {
        width: 200; height: 50
        Text { id: nameField; text: name }
        Text { text: '$' + cost; anchors.left: nameField.right }
        Row {
            anchors.top: nameField.bottom
            spacing: 5
            Text { text: "Attributes:" }
            Repeater {
                model: attributes
                Text { text: description }
            }
        }
    }
}

リストモデルの変更

ListModel のコンテンツは、clear()、append()、set()、insert()、setProperty() メソッドを使用して作成および変更できます。例:

    Component {
        id: fruitDelegate
        Item {
            width: 200; height: 50
            Text { text: name }
            Text { text: '$' + cost; anchors.right: parent.right }

            // Double the price when clicked.
            MouseArea {
                anchors.fill: parent
                onClicked: fruitModel.setProperty(index, "cost", cost * 2)
            }
        }
    }

コンテンツを動的に作成する場合、一度設定された利用可能なプロパティのセットは変更できないことに注意してください。モデルに最初に追加されたプロパティのみが、そのモデルで許可されるプロパティとなります。

WorkerScript でのスレッド化されたリストモデルの使用

ListModel は、WorkerScript と組み合わせて使用することで、複数のスレッドからリストモデルにアクセスできます。これは、リストの変更が同期的で時間がかかる場合に役立ちます。リスト操作を別のスレッドに移すことで、メインの GUI スレッドのブロックを回避できます。

以下は、WorkerScript を使用して、リストモデルに現在の時刻を定期的に追加する例です:

        Timer {
            id: timer
            interval: 2000; repeat: true
            running: true
            triggeredOnStart: true

            onTriggered: {
                var msg = {'action': 'appendCurrentTime', 'model': listModel};
                worker.sendMessage(msg);
            }
        }

同梱されているファイル `dataloader.mjs` は、次のような構成になっています:

WorkerScript.onMessage = function(msg) {
    if (msg.action == 'appendCurrentTime') {
        var data = {'time': new Date().toTimeString()};
        msg.model.append(data);
        msg.model.sync();   // updates the changes to the list
    }
}

メインの例にあるタイマーは、WorkerScript::sendMessage() を呼び出すことで、ワーカースクリプトにメッセージを送信します。このメッセージを受信すると、dataloader.mjs 内でWorkerScript.onMessage() が呼び出され、リストモデルに現在の時刻が追加されます。

外部スレッドからのsync() の呼び出しに注意してください。sync() を呼び出さないと、そのスレッドからリストに加えられた変更は、メインスレッドのリストモデルに反映されません。

「 データモデル 」および Qt Qmlを参照してください。

プロパティのドキュメント

count : int [read-only]

モデル内のデータエントリの数。

dynamicRoles : bool

デフォルトでは、ロールの型は、そのロールが初めて使用された時点で固定されます。 たとえば、「data」というロールを作成してそこに数値を割り当てた場合、その「data」ロールに文字列を割り当てることはできなくなります。ただし、dynamicRoles プロパティが有効になっている場合、特定のロールの型は固定されず、要素ごとに異なる型にすることができます。

dynamicRoles プロパティは、ListModel にデータが追加される前に設定する必要があり、メインスレッドから設定する必要があります。

(ListElement というQML構文を介して)データが静的に定義されているListModel では、dynamicRolesプロパティを有効にすることはできません。

動的ロールを有効にしたListModel を使用すると、パフォーマンスに大きなオーバーヘッドが生じます。そのオーバーヘッドはプラットフォームによって異なりますが、通常、静的ロールタイプを使用する場合に比べて4~6倍程度遅くなります。

動的ロールの使用に伴うパフォーマンス上のオーバーヘッドのため、デフォルトでは無効になっています。

メソッドのドキュメント

void append(jsobject dict)

リストモデルの末尾に、dict に含まれる値を持つ新しい項目を追加します。

fruitModel.append({"cost": 5.95, "name":"Pizza"})

set() およびremove()も参照してください 。

void clear()

モデルからすべてのコンテンツを削除します。特に、get() を使用して取得したすべてのオブジェクトは無効になります。

append()、remove()、およびget()も参照してください 。

var get(int index)

リストモデルのindex にあるアイテムを返します。これにより、JavaScriptからアイテムのデータにアクセスしたり、変更したりすることができます。

Component.onCompleted: {
    fruitModel.append({"cost": 5.95, "name":"Jackfruit"});
    console.log(fruitModel.get(0).cost);
    fruitModel.get(0).cost = 10.95;
}

index は、リスト内の要素でなければなりません。

なお、返されるオブジェクトのプロパティがそれ自体がオブジェクトである場合、そのプロパティもモデルとなります。この get() メソッドは、その要素にアクセスするために使用されます:

fruitModel.append(..., "attributes":
    [{"name":"spikes","value":"7mm"},
     {"name":"color","value":"green"}]);
fruitModel.get(0).attributes.get(1).value; // == "green"

警告: 返されるオブジェクトが 有効な状態を維持することは保証されません。プロパティのバインディングや、その元となるListModel の変更をまたぐデータ保存には使用しないでください。

append() およびclear()も参照してください 。

void insert(int index, jsobject dict)

リストモデルに、位置index に、dict の値を持つ新しい項目を追加します。

fruitModel.insert(2, {"cost": 5.95, "name":"Pizza"})

index は、リスト内の既存の項目への参照であるか、リストの末尾を1つ超えた位置への参照(append と同等)でなければなりません。

set() およびappend()も参照してください 。

void move(int from, int to, int n)

n の項目を、from を1つ分、to を別の位置に移動します。

from と to の範囲は存在している必要があります。たとえば、最初の 3 つの項目をリストの末尾に移動するには:

fruitModel.move(0, fruitModel.count - 3, 3)

append()も参照してください 。

void remove(int index, int count = 1)

モデルから、index にある「count 」個の項目を削除します。

clear()も参照してください 。

void set(int index, jsobject dict)

リストモデルのindex にある項目を、dict の値で更新します。dict に指定されていないプロパティは変更されません。

fruitModel.set(3, {"cost": 5.95, "name":"Pizza"})

index が count() と等しい場合、リストに新しい項目が追加されます。それ以外の場合は、index がリスト内の要素でなければなりません。

append()も参照してください 。

void setProperty(int index, string property, var value)

リストモデル内のindex にある項目のproperty をvalue に変更します。

fruitModel.setProperty(3, "cost", 5.95)

index は、リスト内の要素でなければなりません。

append()も参照してください 。

void sync()

ワーカースクリプトによってリストモデルが変更された後、保存されていない変更内容をすべてリストモデルに書き込みます。

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