TreeView QML 类型

提供树视图以显示从 QAbstractItemModel 中的数据。 更多...

导入语句import QtQuick
Qt 6.3
继承

TableView

属性

信号

方法

详细描述

TreeView 有一个 模型,它定义了要显示的数据,还有一个 代理,它定义了如何显示数据。

TreeView 继承自 TableView。这意味着即使模型具有父子树结构,TreeView 也使用内部代理模型将它转换为由 TableView 可渲染的平面表格模型。树中的每个节点最终占用表中的一行,其中第一列用于渲染树本身。通过调整该列中每个代理项的缩进以对应模型中的父子深度,它最终看起来像一棵树,即使它技术上仍然只是一个项目列表。

为了提供最大灵活性,TreeView 本身不会将代理项目定位为树结构。这项负担放在了代理上。《Qt Quick Controls》提供了一个现成的 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 int 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进行缩进,如果hasChildrentrue,则显示指示器。其他列的委托项此属性设置为false,并显示模型中剩余列的数据(通常不缩进)。
  • required property bool expanded - 如果委托绘制的模型项在视图中展开,则为true
  • required property bool hasChildren - 如果委托绘制的模型项在模型中有子项,则为true
  • required property int depth - 包含委托绘制的模型项的深度。模型项的深度与模型中其祖先的数量相同。

另请参阅必填属性

默认情况下,当您双击行时,TreeView toggle行的展开状态。由于这与双击编辑单元格冲突,TreeView默认将其editTriggers设置为TableView.EditKeyPressed(与TableView不同,后者使用TableView.EditKeyPressed | TableView.DoubleTapped。如果您将editTriggers更改为也包含TableView.DoubleTapped,则双击切换展开状态将会被禁用。

注意:TreeView仅接受继承自QAbstractItemModel的模型。

属性文档

rootIndex : QModelIndex [since 6.6]

此属性持有树中根项的模型索引。默认情况下,这与模型的根索引相同,但您可以将它设置为子索引,以只显示树的分支。将其设置为undefined以显示整个模型。

此属性是在Qt 6.6中引入的。


信号文档

collapsed(row, recursively)

当视图中某一被折叠时,会发出此信号。row将等于导致折叠发生的调用传递的参数(collapse()或collapseRecursively())。如果行是递归折叠的,则recursively将会是true

注意:当一个行递归折叠时,折叠信号只会为该行发出,而不会为其子行发出。

注意:相应的处理器是 onCollapsed

参阅:expanded(),expand(),collapse()和toggleExpanded()。


expanded(row, depth)

当在视图中对一个行展开时,这个信号会被发出。 rowdepth将等于导致展开发生的调用给定的参数(expandexpandRecursively)。在expand的情况下,《i translate="no">depth1。在expandToIndex的情况下,《i translate="no">depth

注意:当一个行递归展开时,展开信号只会为该行发出,而不会为其子行发出。

注意:相应的处理器是 onExpanded

参阅:collapsed(),expand(),collapse()和toggleExpanded()。


方法文档

collapse(row)

关闭在视图中指定的row处的树节点。

row应该是视图中的行(表格行),而不是模型中的行。

注意:此函数不会影响模型,只会影响视图中的视觉表示。

参阅:expand()和isExpanded()。


[since 6.4] collapseRecursively(row = -1)

将视图中的指定row的树节点递归折叠到所有叶子。

对于具有多个根的模型,您还可以使用row等于-1调用此函数。这将折叠所有根。因此,调用collapseRecursively(-1)或简单地调用collapseRecursively()将折叠模型中的所有节点。

row应该是视图中的行(表格行),而不是模型中的行。

注意:此函数不会影响模型,只会影响视图中的视觉表示。

此方法是在Qt 6.4中引入的。

参阅:expandRecursively(),expand(),collapse(),isExpanded()和depth()。


int depth(row)

返回给定row的深度(到根的父亲数量)。

row应该是视图中的行(表格行),而不是模型中的行。如果row不在代码0rows之间,则返回值将为-1

参阅:modelIndex()。


expand(row)

展开视图中给定row的树节点。

row应该是视图中的行(表格行),而不是模型中的行。

注意:此函数不会影响模型,只会影响视图中的视觉表示。

参阅:collapse(),isExpanded()和expandRecursively()。


[since 6.4] expandRecursively(row = -1, depth = -1)

递归地展开视图中指定行 的树节点,直到 深度深度 应相对于 的深度。如果 深度-1,则树将展开到所有叶子节点。

对于具有多个根的模型,您也可以用 等于 -1 来调用此函数。这将展开所有根。因此,调用 expandRecursively(-1, -1) 或简单地调用 expandRecursively() 将展开模型中的所有节点。

row应该是视图中的行(表格行),而不是模型中的行。

注意: 此函数将不会尝试 检索更多 数据。

注意: 此函数将不会影响模型,只会影响视图中的视觉表示。

警告: 如果模型包含大量项目,此函数将需要一些时间来执行。

此方法是在Qt 6.4中引入的。

另请参阅 collapseRecursively()、expand()、collapse()、isExpanded() 和 depth()。


[since 6.4] expandToIndex(QModelIndex index)

从给定的模型 index 展开树,并递归地展开到根。结果将是表示 index 的代理项目在视图中变得可见(除非它最终位于视口外)。为了确保行在视口中可见,您可以执行以下操作:

expandToIndex(index)
forceLayout()
positionViewAtRow(rowAtIndex(index), Qt.AlignVCenter)

此方法是在Qt 6.4中引入的。

另请参阅 expand() 和 expandRecursively()。


bool isExpanded(row)

返回视图中的指定 是否显示为展开。

应该是视图中的行(表格行),而不是模型中的行。如果 不在 0rows 之间,则返回值将为 false


toggleExpanded(row)

切换指定 的树节点是否展开。这是一项方便操作,可以执行

if (isExpanded(row))
    collapse(row)
else
    expand(row)

row应该是视图中的行(表格行),而不是模型中的行。


© 2024 Qt 公司有限公司。本文档中的文档贡献均为其所有者的版权。本文档是根据自由软件基金会发布的 GNU 自由文档许可证第 1.3 版 许可的。Qt 及其相应的标志是芬兰和/或全球其他地区的 Qt 公司的商标。所有其他商标均为其所有者的财产。