TreeView QML Type
提供树形视图,用于显示来自QAbstractItemModel 的数据。更多...
| Import Statement: | import QtQuick |
| Since: | Qt 6.3 |
| Inherits: |
属性
- rootIndex : QModelIndex
(since 6.6)
信号
方法
- void collapse(row)
- void collapseRecursively(row)
(since 6.4) - int depth(row)
- void expand(row)
- void expandRecursively(row, depth)
(since 6.4) - void expandToIndex(QModelIndex index)
(since 6.4) - bool isExpanded(row)
- void toggleExpanded(row)
详细说明
TreeView 包含一个用于定义要显示数据的 `model `,以及一个用于定义数据显示方式的 `delegate `。
TreeView 继承了TableView 。这意味着,尽管模型具有父子树结构,但 TreeView 在内部使用了一个代理模型,将该结构转换为可由TableView 渲染的扁平化表格模型。树中的每个节点最终都会占据表格中的一行,其中第一列用于渲染树本身。 通过根据模型中的父子层级深度对该列中的每个委托项进行缩进,最终呈现的效果将像一棵树,即使从技术上讲它仍然只是一个扁平的项目列表。
声明一个 TreeView
TreeView 是一个数据绑定控件,因此如果没有数据模型,它就无法显示任何内容。在 QML 中无法直接声明树节点。
声明 TreeView 时,需要指定:
- 一个数据模型。TreeView 可以与继承自 `QAbstractItemModel` 的数据模型配合使用。
- 一个委托(delegate)。委托是一个模板,用于指定树节点在用户界面中的显示方式。
TreeView {
// The model needs to be a QAbstractItemModel
model: myTreeModel
// You can set a custom delegate or use a built-in TreeViewDelegate
delegate: TreeViewDelegate {}
}创建数据模型
TreeView 仅接受继承自 `QAbstractItemModel` 的模型。
有关如何创建和使用自定义树模型的信息,请参阅示例:Qt Quick Controls - 目录。
自定义树节点
为了提高灵活性,TreeView 本身不会将委托项定位到树结构中。这项任务由委托来承担。 Qt Quick Controls 提供了一个现成的TreeViewDelegate ,可用于此目的,其优点是开箱即用,并能渲染出符合应用程序运行平台风格的树。
尽管TreeViewDelegate 是可自定义的,但在某些情况下,您可能希望以不同的方式渲染树,或者出于性能等原因,希望确保委托的实现尽可能精简。从头开始创建自己的委托非常简单,因为TreeView提供了一组属性,可用于正确定位和渲染树中的每个节点。
下面是一个带有动画指示器的自定义委托示例:
import QtQuick
import QtQuick.Controls
ApplicationWindow {
width: 800
height: 600
visible: true
TreeView {
id: treeView
anchors.fill: parent
anchors.margins: 10
clip: true
selectionModel: ItemSelectionModel {}
// The model needs to be a QAbstractItemModel
// model: yourTreeModel
delegate: Item {
implicitWidth: padding + label.x + label.implicitWidth + padding
implicitHeight: label.implicitHeight * 1.5
readonly property real indentation: 20
readonly property real padding: 5
// Assigned to by TreeView:
required property TreeView treeView
required property bool isTreeNode
required property bool expanded
required property bool hasChildren
required property int depth
required property int row
required property int column
required property bool current
// Rotate indicator when expanded by the user
// (requires TreeView to have a selectionModel)
property Animation indicatorAnimation: NumberAnimation {
target: indicator
property: "rotation"
from: expanded ? 0 : 90
to: expanded ? 90 : 0
duration: 100
easing.type: Easing.OutQuart
}
TableView.onPooled: indicatorAnimation.complete()
TableView.onReused: if (current) indicatorAnimation.start()
onExpandedChanged: indicator.rotation = expanded ? 90 : 0
Rectangle {
id: background
anchors.fill: parent
color: row === treeView.currentRow ? palette.highlight : "black"
opacity: (treeView.alternatingRows && row % 2 !== 0) ? 0.3 : 0.1
}
Label {
id: indicator
x: padding + (depth * indentation)
anchors.verticalCenter: parent.verticalCenter
visible: isTreeNode && hasChildren
text: "▶"
TapHandler {
onSingleTapped: {
let index = treeView.index(row, column)
treeView.selectionModel.setCurrentIndex(index, ItemSelectionModel.NoUpdate)
treeView.toggleExpanded(row)
}
}
}
Label {
id: label
x: padding + (isTreeNode ? (depth + 1) * indentation : 0)
anchors.verticalCenter: parent.verticalCenter
width: parent.width - padding - x
clip: true
text: model.display
}
}
}
}标记为“required ”的属性将由 TreeView 自动填充,其作用类似于附加属性。通过将其标记为必填属性,委托间接告知 TreeView 应负责为其赋值。以下必填属性可添加到委托中:
required property TreeView treeView- 指向包含该委托项的 TreeView。required property bool isTreeNode- 若委托项代表树中的某个节点,则该属性为true。视图中仅会使用一列来绘制树,因此只有该列中的委托项才会将此属性设置为true。 树中的节点通常应根据其“depth”进行缩进,并且如果“hasChildren”的值是“true”,则应显示指示符。其他列中的委托项将把此属性设置为“false”,并显示模型中其余列的数据(通常不进行缩进)。required property bool expanded- 如果由委托对象绘制的模型项在视图中处于展开状态,则该属性值为true。required property bool hasChildren- 如果委托绘制的模型项在模型中具有子项,则该属性值为true。required property int depth- 包含由委托绘制的模型项的深度。模型项的深度即其在模型中拥有的祖先数量。
另请参阅“必需属性”。
最终用户交互
默认情况下,当您双击一行时,TreeViewtoggles 该行的展开状态。由于这与双击编辑单元格的功能冲突,TreeView 默认将editTriggers 设置为TableView.EditKeyPressed (这与TableView 不同,后者使用TableView.EditKeyPressed | TableView.DoubleTapped )。如果您将editTriggers 修改为同时包含TableView.DoubleTapped ,则双击切换展开状态的功能将被禁用。
属性文档
rootIndex : QModelIndex [since 6.6]
该属性保存树中根节点的模型索引。默认情况下,该索引与模型中的根索引相同,但您可以将其设置为某个子节点的索引,以便仅显示树的某一分支。将其设置为undefined 可显示整个模型。
该属性自 Qt 6.6 起引入。
信号文档
collapsed(row, recursively)
当视图中折叠了一行(row )时,会触发此信号。row 的值将等于引发折叠操作的调用所传入的参数(collapse() 或collapseRecursively())。如果该行是通过递归方式折叠的,则recursively 的值将为true 。
注意:当 行被递归折叠时, 折叠信号仅针对该行发出,而不针对其子行。
注意: 相应的处理程序 是onCollapsed 。
另请参阅 expanded()、expand()、collapse() 以及toggleExpanded()。
expanded(row, depth)
当视图中的“row ”被展开时,会发出此信号。row 和depth 将等于触发展开操作的调用所传入的参数(expand() 或expandRecursively())。对于expand(),depth 始终为1 。对于expandToIndex(),depth 即为目标索引的深度。
注意:当 一行被递归展开时 ,仅会针对该行发出展开信号,而不会针对其子行发出。
注意: 相应的处理程序 是onExpanded 。
另请参阅 collapsed()、expand()、collapse() 和toggleExpanded()。
方法文档
void collapse(row)
在视图中折叠位于给定row 处的树节点。
row 应为视图中的行(表格行),而非模型中的行。
注意:此 函数不会影响模型,仅影响视图中的视觉呈现。
另请参阅 expand() 和isExpanded()。
[since 6.4] void collapseRecursively(row = -1)
将视图中位于给定row 处的树节点递归折叠至所有叶节点。
对于具有多个根节点的模型,您还可以将row 设为-1 来调用此函数。这将折叠所有根节点。因此,调用collapseRecursively(-1)或直接调用collapseRecursively(),将折叠模型中的所有节点。
row 应为视图中的行(表格行),而非模型中的行。
注意:此 函数不会影响模型,仅影响视图中的可视化展示。
该方法在 Qt 6.4 中引入。
另请参阅 expandRecursively()、expand()、collapse()、isExpanded() 以及depth()。
int depth(row)
返回给定row 的深度(即从该行到根节点的父节点数量)。
row 应为视图中的行(表行),而非模型中的行。如果row 不在0 和rows 之间,则返回值为-1 。
另请参阅 modelIndex()。
void expand(row)
展开视图中位于指定row 处的树节点。
row 应为视图中的行(表格行),而非模型中的行。
注意:此 函数不会影响模型,仅影响视图中的可视化呈现。
另请参阅 collapse()、isExpanded() 和expandRecursively()。
[since 6.4] void expandRecursively(row = -1, depth = -1)
递归展开视图中位于指定row 处的树节点,直至depth 。depth 应相对于row 的深度。如果depth 为-1 ,则树将展开至所有叶节点。
对于具有多个根节点的模型,您还可以将row 设为-1 来调用此函数。这将展开所有根节点。因此,调用expandRecursively(-1, -1)或直接调用expandRecursively(),将展开模型中的所有节点。
row 应为视图中的行(表格行),而非模型中的行。
注意:此 函数不会尝试对数据进行fetch more 。
注意:此 函数不会影响模型,仅影响视图中的可视化呈现。
警告:如果 模型包含大量项目,此函数的执行将需要一些时间。
此方法在 Qt 6.4 中引入。
另请参阅 collapseRecursively()、expand()、collapse()、isExpanded() 和depth()。
[since 6.4] void expandToIndex(QModelIndex index)
从给定的模型index 开始展开树结构,并递归地一直向上扩展至根节点。这样一来,代表index 的委托项将在视图中显示出来(除非它最终位于视口之外)。为了确保该行最终显示在视口内,你可以这样做:
expandToIndex(index)
forceLayout()
positionViewAtRow(rowAtIndex(index), Qt.AlignVCenter)此方法在 Qt 6.4 中引入。
另请参阅 expand() 和expandRecursively()。
bool isExpanded(row)
如果视图中给定的row 以展开状态显示,则返回。
row 此处应指视图中的行(表格行),而非模型中的行。如果row 不在0 和rows 之间,则返回值为false 。
void toggleExpanded(row)
用于切换是否展开位于指定row 处的树节点。此功能便于实现以下操作:
if (isExpanded(row))
collapse(row)
else
expand(row)row 此处应指视图中的行(表格行),而非模型中的行。
© 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.