在本页

TableModel QML Type

封装一个简单的表格模型。更多

Import Statement: import Qt.labs.qmlmodels

属性

方法

  • void appendRow(var row)
  • void clear()
  • variant data(QModelIndex index, string role)
  • var getRow(int rowIndex)
  • QModelIndex index(int row, int column)
  • void insertRow(int rowIndex, var row)
  • void moveRow(int fromRowIndex, int toRowIndex, int rows)
  • void removeRow(int rowIndex, int rows)
  • bool setData(QModelIndex index, variant value, string role)
  • void setRow(int rowIndex, var row)

详细说明

TableModel 类型存储 JavaScript/JSON 对象,作为可与TableView 一起使用的表模型的数据。它旨在支持非常简单的模型,而无需在 C++ 中创建自定义的QAbstractTableModel 子类。

import QtQuick
import QtQuick.Window
import Qt.labs.qmlmodels

Window {
    width: 400
    height: 400
    visible: true

    TableView {
        anchors.fill: parent
        columnSpacing: 1
        rowSpacing: 1
        boundsBehavior: Flickable.StopAtBounds

        model: TableModel {
            TableModelColumn { display: "checked" }
            TableModelColumn { display: "amount" }
            TableModelColumn { display: "fruitType" }
            TableModelColumn { display: "fruitName" }
            TableModelColumn { display: "fruitPrice" }

            // Each row is one type of fruit that can be ordered
            rows: [
                {
                    // Each property is one cell/column.
                    checked: false,
                    amount: 1,
                    fruitType: "Apple",
                    fruitName: "Granny Smith",
                    fruitPrice: 1.50
                },
                {
                    checked: true,
                    amount: 4,
                    fruitType: "Orange",
                    fruitName: "Navel",
                    fruitPrice: 2.50
                },
                {
                    checked: false,
                    amount: 1,
                    fruitType: "Banana",
                    fruitName: "Cavendish",
                    fruitPrice: 3.50
                }
            ]
        }
        delegate:  TextInput {
            text: model.display
            padding: 12
            selectByMouse: true

            onAccepted: model.display = text

            Rectangle {
                anchors.fill: parent
                color: "#efefef"
                z: -1
            }
        }
    }
}

模型的初始行数据是通过rows 属性或调用appendRow() 设置的。模型中的每一列都通过声明TableModelColumn 实例来指定,每个实例的顺序决定了其列索引。一旦模型的Component::completed() 信号发出,列和角色就已确定,并在模型的生命周期内固定不变。

要访问特定行,可以使用getRow() 函数。也可以通过rows 属性直接访问模型的 JavaScript 数据,但这种方式无法修改模型数据。

要添加新行,请使用appendRow() 和insertRow() 。要修改现有行,请使用setRow(),moveRow(),removeRow() 和clear() 。

也可以通过委托修改模型的数据,如上例所示:

        delegate:  TextInput {
            text: model.display
            padding: 12
            selectByMouse: true

            onAccepted: model.display = text

            Rectangle {
                anchors.fill: parent
                color: "#efefef"
                z: -1
            }
        }

如果修改角色的数据类型与设置的数据类型不匹配,则会通过QVariant 自动转换。

支持的行数据结构

TableModel 设计用于处理 JavaScript/JSON 数据,其中每一行都是简单的键值对列表:

{
    // Each property is one cell/column.
    checked: false,
    amount: 1,
    fruitType: "Apple",
    fruitName: "Granny Smith",
    fruitPrice: 1.50
},
// ...

由于 Qt 中的模型操作是通过行和列索引完成的,而且对象键是无序的,因此必须通过TableModelColumn 指定每一列。这允许将 Qt 的内置角色映射到每一行对象中的任何属性。

它支持复杂的行结构,但功能有限。由于 TableModel 无法知道每一行的结构,因此无法对其进行操作。因此,TableModel 存储在rows 中的模型数据副本无法与 QML 中设置的源数据保持同步。因此,不支持对数据的操作。

例如,假设你想使用一个数据源,其中每一行都是一个数组,每一个单元格都是一个对象。要在 TableModel 中使用该数据源,需要定义一个 getter:

TableModel {
    TableModelColumn {
        display: function(modelIndex) { return rows[modelIndex.row][0].checked }
    }
    // ...

    rows: [
        [
            { checked: false, checkable: true },
            { amount: 1 },
            { fruitType: "Apple" },
            { fruitName: "Granny Smith" },
            { fruitPrice: 1.50 }
        ]
        // ...
    ]
}

上面的行就是复杂行的一个示例。

注意: 使用复杂行时,不支持行操作函数,如appendRow(),removeRow() 等。

将 DelegateChooser 与 TableModel 结合使用

对于大多数实际用例,建议使用DelegateChooser 作为使用 TableModel 的TableView 的委托。这样就可以在相关委托中使用特定角色。例如,上面的代码段可以改写成这样:使用DelegateChooser

import QtQuick
import QtQuick.Controls
import Qt.labs.qmlmodels

ApplicationWindow {
    width: 400
    height: 400
    visible: true

    TableView {
        anchors.fill: parent
        columnSpacing: 1
        rowSpacing: 1
        boundsBehavior: Flickable.StopAtBounds

        model: TableModel {
            TableModelColumn { display: "checked" }
            TableModelColumn { display: "amount" }
            TableModelColumn { display: "fruitType" }
            TableModelColumn { display: "fruitName" }
            TableModelColumn { display: "fruitPrice" }

            // Each row is one type of fruit that can be ordered
            rows: [
                {
                    // Each property is one cell/column.
                    checked: false,
                    amount: 1,
                    fruitType: "Apple",
                    fruitName: "Granny Smith",
                    fruitPrice: 1.50
                },
                {
                    checked: true,
                    amount: 4,
                    fruitType: "Orange",
                    fruitName: "Navel",
                    fruitPrice: 2.50
                },
                {
                    checked: false,
                    amount: 1,
                    fruitType: "Banana",
                    fruitName: "Cavendish",
                    fruitPrice: 3.50
                }
            ]
        }
        delegate: DelegateChooser {
            DelegateChoice {
                column: 0
                delegate: CheckBox {
                    checked: model.display
                    onToggled: model.display = checked
                }
            }
            DelegateChoice {
                column: 1
                delegate: SpinBox {
                    value: model.display
                    onValueModified: model.display = value
                }
            }
            DelegateChoice {
                delegate: TextField {
                    text: model.display
                    selectByMouse: true
                    implicitWidth: 140
                    onAccepted: model.display = text
                }
            }
        }
    }
}

首先声明最特殊的委托:索引01 中的列具有boolinteger 数据类型,因此它们分别使用CheckBoxSpinBox 。其余列可以简单地使用TextField ,因此最后声明该委托作为备用。

将 TableModel 与外部 JSON 源一起使用

如果 JSON 对象中的数据结构与 TableModel 定义的结构相匹配,则可使用行属性将其直接分配给模型。数据中的所有行必须符合模型定义的列。

例如,如果模型定义为

            model: TableModel {
                TableModelColumn { display: "driverId" }
                TableModelColumn { display: "code" }
                TableModelColumn { display: "url" }
                TableModelColumn { display: "givenName" }
                TableModelColumn { display: "familyName" }
                TableModelColumn { display: "dateOfBirth" }
                TableModelColumn { display: "nationality" }
            }

源数据具有所需的数据,但不一定具有所需的结构,您可以将其下载并解析为符合模型定义结构的表单,然后直接分配结果。

    function requestJson() {
        let doc = new XMLHttpRequest()
        doc.onreadystatechange = function() {
            if (doc.readyState === XMLHttpRequest.DONE) {
                var root = JSON.parse(doc.responseText)
                var race = root.MRData.RaceTable.Races[0]
                var raceResults = race.Results
                var drivers = []
                for (let i = 0; i < raceResults.length; ++i) {
                    drivers.push(raceResults[i].Driver)
                }
                tableView.model.rows = drivers
                print(JSON.stringify(drivers))
            }
        }

        doc.open("GET", "https://api.jolpi.ca/ergast/f1/2005/1/results.json")
        doc.send()
    }

并可直接分配结果

    Component.onCompleted: requestJson()

您也可以通过导入 JavaScript 文件作为模块来提供 JSON 对象。有关如何操作的示例,请参阅TreeModel 文档。

警告: 确保 JSON 数据来自可信来源。由于模型会根据输入内容自动填充行,因此畸形或不可信的 JSON 可能会导致意外行为或性能问题。

另请参阅 TableModelColumnTableViewQAbstractTableModel

属性文档

columnCount : int [read-only]

此只读属性保存模型中的列数。

在设置rows 属性或首次调用appendRow() 后,列数在模型的生命周期内是固定的。

rowCount : int [read-only]

此只读属性保存模型中的行数。

每当从模型中添加或删除行时,该值都会发生变化。

rows : var

该属性以数组行的形式保存模型数据:

            rows: [
                {
                    // Each property is one cell/column.
                    checked: false,
                    amount: 1,
                    fruitType: "Apple",
                    fruitName: "Granny Smith",
                    fruitPrice: 1.50
                },
                {
                    checked: true,
                    amount: 4,
                    fruitType: "Orange",
                    fruitName: "Navel",
                    fruitPrice: 2.50
                },
                {
                    checked: false,
                    amount: 1,
                    fruitType: "Banana",
                    fruitName: "Cavendish",
                    fruitPrice: 3.50
                }
            ]

另请参阅 getRow(),setRow(),moveRow(),appendRow(),insertRow(),clear(),rowCount, 和columnCount

方法文档

void appendRow(var row)

在模型末尾添加新的一行,其数值(单元格)在row 中。

model.appendRow({
    checkable: true,
    amount: 1,
    fruitType: "Pear",
    fruitName: "Williams",
    fruitPrice: 1.50,
})

另请参阅 insertRow()、setRow() 和removeRow()。

void clear()

删除模型中的所有行。

另请参见 removeRow().

variant data(QModelIndex index, string role)

从给定index 的表格单元格中返回属于给定role 的数据。

另请参阅 index() 和setData()。

var getRow(int rowIndex)

返回模型中位于rowIndex 的记录。

请注意,这相当于直接通过rows 属性访问该行:

Component.onCompleted: {
    // These two lines are equivalent.
    console.log(model.getRow(0).display);
    console.log(model.rows[0].fruitName);
}

注意: 返回的对象不能用于修改模型的内容;请使用setRow() 代替。

另请参阅 setRow()、appendRow()、insertRow()、removeRow() 和moveRow()。

QModelIndex index(int row, int column)

返回引用给定rowcolumnQModelIndex 对象,该对象可传递给data() 函数以获取该单元格的数据,或传递给setData() 以编辑该单元格的内容。

import QtQml 2.14
import Qt.labs.qmlmodels 1.0

TableModel {
    id: model

    TableModelColumn { display: "fruitType" }
    TableModelColumn { display: "fruitPrice" }

    rows: [
        { fruitType: "Apple", fruitPrice: 1.50 },
        { fruitType: "Orange", fruitPrice: 2.50 }
    ]

    Component.onCompleted: {
        for (var r = 0; r < model.rowCount; ++r) {
            console.log("An " + model.data(model.index(r, 0)).display +
                        " costs " + model.data(model.index(r, 1)).display.toFixed(2))
        }
    }
}

另请参阅 QML 中的 QModelIndex 和相关类以及data()。

void insertRow(int rowIndex, var row)

rowIndex 的位置为模型添加一行新数据,其值(单元格)位于row

model.insertRow(2, {
    checkable: true, checked: false,
    amount: 1,
    fruitType: "Pear",
    fruitName: "Williams",
    fruitPrice: 1.50,
})

rowIndex 必须指向表中的现有项,或表末尾的一项(相当于appendRow()) 。

另请参阅 appendRow()、setRow()、removeRow() 和rowCount

void moveRow(int fromRowIndex, int toRowIndex, int rows)

rowsfromRowIndex 的索引移至toRowIndex 的索引。

from 和 to 的范围必须存在;例如,将前 3 个项目移至列表末尾:

model.moveRow(0, model.rowCount - 3, 3)

另请参阅 appendRow()、insertRow()、removeRow() 和rowCount

void removeRow(int rowIndex, int rows = 1)

rowIndex 从模型中删除一些rows

另请参见 clear() 和rowCount

bool setData(QModelIndex index, variant value, string role)

在给定index 的表格单元格中插入或更新以role 命名的数据字段,value 。成功则返回 true,失败则返回 false。

另请参阅 data() 和index()。

void setRow(int rowIndex, var row)

row 更改模型中rowIndex 的行。

row 中必须包含所有列/单元格,且顺序正确。

model.setRow(0, {
    checkable: true,
    amount: 1,
    fruitType: "Pear",
    fruitName: "Williams",
    fruitPrice: 1.50,
})

如果rowIndexrowCount() 相等,则会在模型中添加新行。否则,rowIndex 必须指向模型中的现有行。

另请参阅 appendRow(),insertRow() 和rowCount

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