TableModel QML Type
封装了一个简单的表模型。更多...
| Import Statement: | import Qt.labs.qmlmodels |
属性
- columnCount : int
- rowCount : int
- rows : var
方法
- 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 配合使用,请定义一个获取器:
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 }
]
// ...
]
}上文中的行即为复杂行的一种示例。
在 TableModel 中使用 DelegateChooser
对于大多数实际应用场景,建议将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
}
}
}
}
}最具体的委托首先声明:索引为0 和1 的列具有bool 和integer 数据类型,因此它们分别使用CheckBox 和SpinBox 。其余列只需使用TextField ,因此该委托作为备用方案最后声明。
将 TableModel 与外部 JSON 数据源结合使用
如果 JSON 对象中的数据结构与 TableModel 定义的结构匹配,则可使用 rows 属性将其直接赋值给该模型。数据中的所有行都必须符合模型定义的列结构。
例如,如果模型定义如下:
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 可能会导致意外行为或性能问题。
另请参阅 TableModelColumn 、TableView 以及QAbstractTableModel 。
属性文档
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 的表格单元格中的数据。
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)
返回一个QModelIndex 对象,该对象引用了给定的row 和column 。该对象可传递给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))
}
}
}另请参阅 QModelIndex 以及 QML 中的相关类和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)
将位于索引fromRowIndex 的rows 移动到索引toRowIndex 。
源范围和目标范围必须存在;例如,要将前 3 个项目移至列表末尾:
model.moveRow(0, model.rowCount - 3, 3)另请参阅 appendRow()、insertRow()、removeRow() 以及rowCount 。
void removeRow(int rowIndex, int rows = 1)
从模型中移除位于rowIndex 上的若干个rows 文件。
bool setData(QModelIndex index, variant value, string role)
使用value 在表中位于给定位置index 的单元格中插入或更新名为role 的数据字段。若操作成功则返回 true,否则返回 false。
void setRow(int rowIndex, var row)
将模型中rowIndex 处的行替换为row 。
row 中必须包含所有列/单元格,且顺序必须正确。
model.setRow(0, {
checkable: true,
amount: 1,
fruitType: "Pear",
fruitName: "Williams",
fruitPrice: 1.50,
})如果 `rowIndex ` 等于 `rowCount()`,则向模型中追加一行。否则,`rowIndex ` 必须指向模型中的一行。
© 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.