使用QML的ListView自制树形结构图TreeView

5 篇文章 1 订阅

背景

感觉QML自带的TreeView不是很好用,用在文件路径树形结构比较多,但是想用在自己数据里,就不太方便了,所以自己做一个。

用‘ListView里迭代ListView’的方法,制作树形结构,成果图:
在这里插入图片描述

代码

新建一个MyTreeView.qml用来写主要代码,再在main.qml中调用MyTreeView,并为它填充数据。
这里数据是在qml中用JSON.parse构建的json数据,也可以在cpp中用QJsonArray和QJsonObject来构建数据。

// MyTreeView.qml
import QtQuick 2.0

Item {
    id: root
    property alias model: list_view.model

    ListView {
        id: list_view
        width: contentWidth
        anchors.fill: parent
        anchors.margins: 10
        delegate: list_delegate
    }

    Component {
        id: list_delegate

        Item{
            id: list_itemgroup
            width: leftLine.width + centre.width + rightLine.width + listView.width
            height: Math.max(centre.height, listView.height)
            property int lineY: leftLine.y


            Rectangle {
                id: leftLine
                width: 20
                height: 1
                color: "#d3dee4"
                visible: modelData.id >= 0
                anchors.verticalCenter: centre.verticalCenter
            }

            Rectangle {
                id: centre
                width: 150
                height: 50
                color: "#d3dee4"
                radius: 5
                anchors.left: leftLine.right
                anchors.verticalCenter: parent.verticalCenter
                Text {
                    text: qsTr(modelData.name)
                    font.pixelSize: 20
                    font.bold: true
                    anchors.centerIn: parent
                }
            }

            Rectangle {
                id: rightLine
                width: 20
                height: 1
                color: "#d3dee4"
                visible: modelData.subnodes.length > 0
                anchors.verticalCenter: centre.verticalCenter
                anchors.left: centre.right
            }

            Rectangle {
                id: verticalLine
                width: 1
                color: "#d3dee4"
                x: parent.width + 1
                visible: modelData.subnodes.length > 1
                anchors.top: parent.top
                anchors.bottom: parent.bottom
            }

            ListView {
                id: listView
                delegate: list_delegate
                height: contentHeight
                width: contentWidth
                anchors.right: parent.right
                model: modelData.subnodes
                spacing: 10
                onModelChanged: {
                }
            }

            Component.onCompleted: {
                listView.forceLayout()  // 要先确保listView加载子项完成
                // 画一下verticalLine的y坐标起点和终点
                for (var i = 0; i < modelData.subnodes.length; i++) {
                    var item = listView.itemAtIndex(i)
                    if (i === 0) {
                        verticalLine.anchors.topMargin = item.lineY
                    } else if (i === modelData.subnodes.length-1) {
                        verticalLine.anchors.bottomMargin = item.lineY
                    }
                }
            }
        }
    }
}

// main.qml
import QtQuick 2.15
import QtQml.Models 2.15
import QtQuick.Window 2.12
import QtQuick.Controls 1.4

Window {
    id: window_
    width: 940
    height: 680
    visible: true
    title: qsTr("Hello World")
    color: "#103e6f"


    Item {
        id: home
        anchors.fill: parent

        MyTreeView {
            id: treeView
            anchors.fill: parent
        }
    }



    Component.onCompleted: {
        var data = JSON.parse('[{
                "id": -1,
                "name": "目录",
                "subnodes": [{
                    "id": 0,
                    "name": "第一本书",
                    "subnodes": [{
                        "id": 1,
                        "name": "第一章",
                        "subnodes": [{
                            "id": 2,
                            "name": "第一节",
                            "subnodes": []
                        }, {
                            "id": 3,
                            "name": "第二节",
                            "subnodes": []
                        }]
                    }, {
                        "id": 4,
                        "name": "第二章",
                        "subnodes": [{
                            "id": 5,
                            "name": "第一节",
                            "subnodes": []
                        }, {
                            "id": 6,
                            "name": "第二节",
                            "subnodes": []
                        }, {
                            "id": 7,
                            "name": "第三节",
                            "subnodes": []
                        }]
                    }]
                }, {
                    "id": 8,
                    "name": "第二本书",
                    "subnodes": [{
                        "id": 9,
                        "name": "第一章",
                        "subnodes": [{
                            "id": 10,
                            "name": "第一节",
                            "subnodes": []
                        }, {
                            "id": 11,
                            "name": "第二节",
                            "subnodes": []
                        }]
                    }, {
                        "id": 12,
                        "name": "第二章",
                        "subnodes": [{
                            "id": 13,
                            "name": "第一节",
                            "subnodes": []
                        }]
                    }]
                }]
            }]')
        treeView.model = data
    }

}

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值