您当前的位置: 首页 > 

龚建波

暂无认证

  • 4浏览

    0关注

    313博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

QML自定义一个TreeView,使用ListView递归

龚建波 发布时间:2019-05-26 14:05:05 ,浏览量:4

0.前言

在 Qt5 的 QtQuick.Controls 2.x 中还没有 TreeView 这个控件(在 Qt6 中出了一个继承自 TableView 的 TreeView),而且 QtQuick.Controls 1.x 中的也需要配合 C++ model 来自定义,对于一些简单的需求还要写 C++ model 就显得费事儿。

参照别人的自定义 TreeView 实现,我也使用 ListView 嵌套的方式做了一个简易的 TreeView,主要功能就是根据 json 结构来生成一个树状列表。

(2022-05-28)在最初的版本没考虑 ListView 超过 cache 范围自动销毁的问题,改版后勾选等状态放到外部数组中,释放后重新创建 delegate item 时,会从外部数组中取值进行判断该 item 是否勾选。

1.展示

先看看ui效果图-1和自己的demo图-2。三级目录,其中最后一级是勾选框。我用黑色表示无子项,白色有子项已展开,灰色有子项未展开,绿色已勾选,红色未勾选。实际使用时会替换为image。

     

//PS.后面完善了下,效果如下图

代码github:https://github.com/gongjianbo/QmlTreeView

主要代码:

//TreeView.qml

import QtQuick 2.7
import QtQuick.Controls 2.7

//代码仅供参考,很多地方都不完善
//还有一些样式没有导出,可以根据需求自己定义
//因为ListView有回收策略,除非cacheBuffer设置很大,所以状态不能保存在delegate.item中
//需要用外部变量或者model来存储delegate.item的状态
Rectangle {
    id: control

    property string currentItem //当前选中item

    property int spacing: 10    //项之间距离
    property int indent: 5      //子项缩进距离,注意实际还有icon的距离
    property string onSrc: "qrc:/img/on.png"
    property string offSrc: "qrc:/img/off.png"
    property string checkedSrc: "qrc:/img/check.png"
    property string uncheckSrc: "qrc:/img/uncheck.png"

    property var checkedArray: [] //当前已勾选的items
    property bool autoExpand: true

    //背景
    color: Qt.rgba(2/255,19/255,23/255,128/255)
    border.color: "darkCyan"
    property alias model: list_view.model
    ListView {
        id: list_view
        anchors.fill: parent
        anchors.margins: 10
        //model: //model由外部设置,通过解析json
        property string viewFlag: ""
        delegate: list_delegate
        clip: true
        onModelChanged: {
            console.log('model change')
            checkedArray=[]; //model切换的时候把之前的选中列表清空
        }
    }
    Component {
        id: list_delegate
        Row{
            id: list_itemgroup
            spacing: 5
            property string parentFlag: ListView.view.viewFlag
            //以字符串来标记item
            //字符串内容为parent.itemFlag+model.index
            property string itemFlag: parentFlag+"-"+(model.index+1)

            //canvas 画项之间的连接线
            Canvas {
                id: list_canvas
                width: item_titleicon.width+10
                height: list_itemcol.height
                //开了反走样,线会模糊看起来加粗了
                antialiasing: false
                //最后一项的连接线没有尾巴
                property bool isLastItem: (model.index===list_itemgroup.ListView.view.count-1)
                onPaint: {
                    var ctx = getContext("2d")
                    var i=0
                    //ctx.setLineDash([4,2]); 遇到个大问题,不能画虚线
                    // setup the stroke
                    ctx.strokeStyle = Qt.rgba(201/255,202/255,202/255,1)
                    ctx.lineWidth=1
                    // create a path
                    ctx.beginPath()
                    //用短线段来实现虚线效果,判断里-3是防止width(4)超过判断长度
                    //此外还有5的偏移是因为我image是透明背景的,为了不污染到图标
                    //这里我是虚线长4,间隔2,加起来就是6一次循环
                    //效果勉强
                    ctx.moveTo(width/2,0) //如果第一个item虚线是从左侧拉过来,要改很多
                    for(i=0;i            
关注
打赏
1655829268
查看更多评论
0.2033s