Qt Quick使用listview实现treeview的方法

  • 背景

    由于在项目中需要实现treeview中的单元实现上下拖动功能,Qt Quick自身的treeview虽然能够实现树形结构功能,但却无法实现树形节点的拖动功能。于是考虑用listview来实现treeview的功能,在网上提的比较多的是listview+repeat方法,手动实践过,可以实现预期效果,但这个方法最大的缺点是如果有三个树形节点单元,在鼠标滚动时,listview的滚动条上的滑块定位不准而且时常的跳上跳下,已闭合的树形节点也会在滚动时被自动打开,数据量几千条时有时listview中的数据会跑飞,就是没有了。调试过发现滚动鼠标滚轮时会自动执行mousearea的doubleclicked事件,所以感觉这个方法不靠谱。

  • 方法思路

    于是考虑自己用listview+逻辑组合的方式实现treeview,即在model里面做好树形显示的一级节点二级节点组合,最后一次性加载到listview显示上就可以啦。将所有的一级节点放在一个list中,二级节点放在一级节点的后面。写一个类来存放当前数据节点信息,而QList<NodeItem*> m_node_item_list;用来存放其下一级节点信息。最后逐条添加到listview的model中即可。
    树形model的加载方法可以借鉴下面的例子:如init_shoot_sequence_list_model(),该函数可以根据传入的true 或false可实现treeview与纯listview的转换。

class NodeItem
{
//    Q_OBJECT
public:
    NodeItem( int n_node_id, int n_region_id, QString n_region_name, int n_parent_id, int n_device_id, QString s_device_content, int n_level);

    int get_node_id() { return mn_node_id; }

    int get_region_id() { return mn_region_id; }

    QString get_region_name() { return ms_region_name; }

    int get_parent_id() { return mn_parent_id; }

    int get_device_id() { return mn_device_id; }

    QString get_device_content() { return ms_device_content; }

    int get_shoot_sequence_level() { return mn_level; }

    QList<NodeItem*> m_node_item_list;

private:
    int mn_node_id;
    int mn_region_id;
    QString ms_region_name;
    int mn_parent_id;
    int mn_device_id;
    QString ms_device_content;
    int mn_level;

};
import QtQuick 2.3
import QtQuick.Window 2.2

Window {
    visible: true
    width: 480
    height: 640
    Rectangle {
        anchors.fill: parent
        ListModel{
            id: objmodel

        }
        Component {
            id: shoot_sequence_delegate
            Item {
                id: unit_item
                width: parent.width
                height: 30
                Row{
                    anchors.left: parent.left
                    anchors.verticalCenter: parent.verticalCenter
                    spacing: 8
                    Text {
                        id: tag_txt
                        text: tag
                        color: unit_item.ListView.isCurrentItem? "blue":"black"
                        font.pixelSize: 20

                    }
                    Text {
                        id: name_txt
                        text: name
                        color: unit_item.ListView.isCurrentItem? "blue":"black"
                        font.pixelSize: 20
                    }
                }
                MouseArea {
                    id: mousearea
                    anchors.fill: parent
                    onClicked: {
                        shoot_sequence_listview.currentIndex = index
                    }
                    onDoubleClicked: {
                        shoot_sequence_listview.currentIndex = index
                        var data = objmodel.get(shoot_sequence_listview.currentIndex);
                        if( data.level_status === "0" ) {
                            var n = data.model_index
                            var n_device_node_count = shoot_sequences_list_model.get_device_node_count_from_list( data.model_index )
                            if( data.visible_status === "true" ) {
                                objmodel.setProperty(shoot_sequence_listview.currentIndex, "visible_status", "false")
                                objmodel.setProperty(shoot_sequence_listview.currentIndex, "tag", "+")
                                objmodel.remove( shoot_sequence_listview.currentIndex+1, n_device_node_count )
                            } else {
                                objmodel.setProperty(shoot_sequence_listview.currentIndex, "visible_status", "true")
                                objmodel.setProperty(shoot_sequence_listview.currentIndex, "tag", "-")
                                for( var j=0; j<n_device_node_count; j++ ) {
                                    var n_node_id = shoot_sequences_list_model.get_node_id_from_list( n, j )
                                    var n_region_id = shoot_sequences_list_model.get_region_id_from_list( n, j )
                                    var s_region_name = shoot_sequences_list_model.get_region_name_from_list( n, j )
                                    var n_parent_id = shoot_sequences_list_model.get_parent_id_from_list( n, j )
                                    var n_device_id = shoot_sequences_list_model.get_device_id_from_list( n, j )
                                    var s_device_content = shoot_sequences_list_model.get_device_content_from_list( n, j )
                                    var n_shoot_level = shoot_sequences_list_model.get_shoot_sequence_level_from_list( n, j )
                                    objmodel.insert(shoot_sequence_listview.currentIndex+j+1, {"name":""+s_device_content, "tag":"    ", "level_status":""+n_shoot_level, "regin_id": n_region_id, "visible_status":"true", "visible_status":"true", "model_index":""+n})
                                }
                            }
                        }
                    }
                }

            }
        }

        property int flag: 0
        ListView {
            id: shoot_sequence_listview
            anchors.fill: parent
            delegate: shoot_sequence_delegate
            model:objmodel
            interactive: false
            focus: true

            Component.onCompleted: {
//                shoot_sequences_list_model.set_shoot_sequence_list_model( "26", true );
//                init_shoot_sequence_list_model( true )
                shoot_sequences_list_model.set_shoot_sequence_list_model( "26", false );
                init_shoot_sequence_list_model( false )
            }

            function init_shoot_sequence_list_model(  b_last_level_status ) {
                objmodel.clear()
                if( b_last_level_status ) {
                    var n_list_count = shoot_sequences_list_model.get_shoot_sequence_list_model_count()
                    for( var i=0; i<n_list_count; i++ ) {
                        var node_id = shoot_sequences_list_model.get_node_id( i )
                        var region_id = shoot_sequences_list_model.get_region_id( i )
                        var region_name = shoot_sequences_list_model.get_region_name( i )
                        var parent_id = shoot_sequences_list_model.get_parent_id( i )
                        var device_id = shoot_sequences_list_model.get_device_id( i )
                        var device_content = shoot_sequences_list_model.get_device_content( i )
                        var shoot_level = shoot_sequences_list_model.get_shoot_sequence_level( i )
                        objmodel.append({"name":""+device_content, "tag":"  ", "level_status":""+shoot_level, "regin_id": region_id, "visible_status":"true", "model_index":"-1"})

                    }
                } else {
                    var n_region_list_count = shoot_sequences_list_model.get_shoot_sequence_list_model_count()
                    var n_device_node_count;
                    for( var n=0; n<n_region_list_count; n++ ) {
                        node_id = shoot_sequences_list_model.get_node_id( n )
                        region_id = shoot_sequences_list_model.get_region_id( n )
                        region_name = shoot_sequences_list_model.get_region_name( n )
                        parent_id = shoot_sequences_list_model.get_parent_id( n )
                        device_id = shoot_sequences_list_model.get_device_id( n )
                        device_content = shoot_sequences_list_model.get_device_content( n )
                        shoot_level = shoot_sequences_list_model.get_shoot_sequence_level( n )
                        objmodel.append({"name":region_name, "tag":"-", "level_status":""+shoot_level, "regin_id": region_id, "visible_status":"true", "model_index":""+n})
                        n_device_node_count = shoot_sequences_list_model.get_device_node_count_from_list( n )
                        console.log("n_device_node_count: "+n_device_node_count)

                        for( var j=0; j<n_device_node_count; j++ ) {
                            var n_node_id = shoot_sequences_list_model.get_node_id_from_list( n, j )
                            var n_region_id = shoot_sequences_list_model.get_region_id_from_list( n, j )
                            var s_region_name = shoot_sequences_list_model.get_region_name_from_list( n, j )
                            var n_parent_id = shoot_sequences_list_model.get_parent_id_from_list( n, j )
                            var n_device_id = shoot_sequences_list_model.get_device_id_from_list( n, j )
                            var s_device_content = shoot_sequences_list_model.get_device_content_from_list( n, j )
                            var n_shoot_level = shoot_sequences_list_model.get_shoot_sequence_level_from_list( n, j )
                            objmodel.append({"name":""+s_device_content, "tag":"    ", "level_status":""+n_shoot_level, "regin_id": n_region_id, "visible_status":"true", "model_index":""+n})

                        }
                    }
                }
            }
        }
    }

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱技术爱生活

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值